逍
逍遥泿子
Unregistered / Unconfirmed
GUEST, unregistred user!
现要做一个基于TCP/IP SOCKET通讯的软件
客户端: 是一个DLL,调用时传入一个字符串。
对外函数: Function UnloadData(DataStr: String): String;
DLL要做成SOCKET 客户端,DataStr为上传报文,服务端应答后返回信息为函数结果。
服务端:接收客户端传入字符串,并解释返回结果信息
在这样的处理中,Delphi用的是控件, 客户端怎么用阻塞处理方式/为什么有时会收到一些乱码?
我的源代码:
unit Unit1;
TServerThread = Class(TServerClientThread)
public
procedure ClientExecute; override;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Port := 1024;
ServerSocket1.Open;
end;
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
//客户端建立连接时执行,怎么确定线程安全
SocketThread := TServerThread.Create(False, ClientSocket);
end;
procedure TServerThread.ClientExecute;
const
MSG_MAX_LEN = 8096;
bufferSize = 8096;
var
pPush: PChar; //接收字符串
lwReadCount: LongInt; //读取数
Buf: Array[0..MSG_MAX_LEN - 1] of Char; //
Stream: TWinSocketStream; //
ResultStr: String; //内存流
Buffer: Pointer;
begin
try
while (not Terminated) and ClientSocket.Connected do
begin
Stream := TWinSocketStream.Create(ClientSocket, 6000);
try
if (not Terminated) and (ClientSocket.Connected)
and Stream.WaitForData(6000) then
begin
GetMem(Buffer, BufferSize); //分配固定大小
lwReadCount := Stream.Read(Buf, MSG_MAX_LEN);
if lwReadCount = 0 then //不能在60秒内完成
begin
//读取失败
ClientSocket.Close;
Terminate;
end
else
begin
//放入队列
pPush := AllocMem(lwReadCount); //分配内存块,并初始化为0
CopyMemory(pPush, @Buf, lwReadCount); //内存拷贝
//
ResultStr := pPush;
ResultStr := Copy(ResultStr, 3, Length(ResultStr)-2);
//收到服务端信息
Form1.Memo2.Lines.Add(ResultStr);
//服务端返回值
ResultStr := 'R:'+ResultStr + '@' + ResultStr;
//
ClientSocket.SendText(ResultStr);
ClientSocket.Close;
//Terminate;
end;
end
else
begin
ClientSocket.Close;
Terminate;
end;
finally
Stream.Free;
end;
end;//while
except
ClientSocket.Close;
Terminate;
end;
end;
DLL动态库:
unit SockDM;
procedure Delay(dwMilliseconds: Longint); //延时
var
iStart, iStop: DWORD;
begin
iStart := GetTickCount;
repeat
iStop := GetTickCount;
until (iStop - iStart) >= dwMilliseconds;
end;
procedure TSDM.DataModuleCreate(Sender: TObject);
var
IniFile: TInifile;
begin
//取服务器IP地址、端口号
IniFile := TIniFile.Create('MyApp.ini');
try
ClientSocket.Address := IniFile.ReadString('RomterServer', 'Server', '');
ClientSocket.Port := IniFile.ReadInteger('RomterServer', 'Port', 0);
//
ClientSocket.Address := '127.0.0.1';
ClientSocket.Port := 1024;
finally
IniFile.Free;
end;
end;
//阻塞方式处理流程*******************************************************
Function TSDM.UnLoadMsg(Msg: String; ctClientType: TClientType): String;
var
TimeBegin, Time: DWORD; //起始时间
TimeOut: Integer; //超时阀值
ResultStr: String; //返回处理
begin
//客户端连接
ErrorNum := 0;
if ClientSocket.Active then ClientSocket.Active := False;
ClientSocket.Address := '127.0.0.1';
ClientSocket.Port := 1024;
ClientSocket.ClientType := ctClientType; //阻塞方式
ClientSocket.Open; //打开客户端连接
timeBegin := GetTickCount; //起始时间
while True do
begin
//判断网络连接成功
if not ClientSocket.Socket.Connected then
begin
ClientSocket.Active := True;
Continue;
end;
//字符上传,加发送标识(S
ClientSocket.Socket.SendStream(TStringStream.Create('S:'+Msg)); //上传数据(数据流方式)
if ErrorNum > 5 then
begin
Result := '-10001|系统错误,可能是服务端没有启动!';
Break; //系统错误,不能返回值
end;
if ClientSocket.ClientType = ctBlocking then //阻塞方法需要主动去读
begin
ReadStr := ClientSocket.Socket.ReceiveText;
end;
if LeftStr(ReadStr, 2) = 'R:' then //根据返回值信息标识
begin
//已经收到数据, 非阻塞方式数据由OnRead事件触发
Result := Copy(ReadStr, 3, Length(ReadStr)-2); //返回时去标识号
Break;
end;
//是否超时处理
Time := GetTickCount;
if Time-TimeBegin >= 6000 then
begin
//网络超时
Result := '-10001|网络超时错误!';
Break;
end
else
begin
//延时100微妙
Delay(100);
end;
end;
end;
procedure TSDM.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
begin
ReadStr := Socket.ReceiveText;
end;
procedure TSDM.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Inc(ErrorNum);
ErrorCode := 0;
//写客户端连接错误日志
end;
上面处理也可以通/
但存在下面几个问题:
1、客户端连接后怎么还是Conneted = False
2、服务端在数据传输后立即关掉了
3、传输中存在乱码
4、怎么没有说如何创建流套接字?
5、SendText与SendStream有什么区别?
有没有用Delphi做过SOCKET.通讯的?
客户端: 是一个DLL,调用时传入一个字符串。
对外函数: Function UnloadData(DataStr: String): String;
DLL要做成SOCKET 客户端,DataStr为上传报文,服务端应答后返回信息为函数结果。
服务端:接收客户端传入字符串,并解释返回结果信息
在这样的处理中,Delphi用的是控件, 客户端怎么用阻塞处理方式/为什么有时会收到一些乱码?
我的源代码:
unit Unit1;
TServerThread = Class(TServerClientThread)
public
procedure ClientExecute; override;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Port := 1024;
ServerSocket1.Open;
end;
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
//客户端建立连接时执行,怎么确定线程安全
SocketThread := TServerThread.Create(False, ClientSocket);
end;
procedure TServerThread.ClientExecute;
const
MSG_MAX_LEN = 8096;
bufferSize = 8096;
var
pPush: PChar; //接收字符串
lwReadCount: LongInt; //读取数
Buf: Array[0..MSG_MAX_LEN - 1] of Char; //
Stream: TWinSocketStream; //
ResultStr: String; //内存流
Buffer: Pointer;
begin
try
while (not Terminated) and ClientSocket.Connected do
begin
Stream := TWinSocketStream.Create(ClientSocket, 6000);
try
if (not Terminated) and (ClientSocket.Connected)
and Stream.WaitForData(6000) then
begin
GetMem(Buffer, BufferSize); //分配固定大小
lwReadCount := Stream.Read(Buf, MSG_MAX_LEN);
if lwReadCount = 0 then //不能在60秒内完成
begin
//读取失败
ClientSocket.Close;
Terminate;
end
else
begin
//放入队列
pPush := AllocMem(lwReadCount); //分配内存块,并初始化为0
CopyMemory(pPush, @Buf, lwReadCount); //内存拷贝
//
ResultStr := pPush;
ResultStr := Copy(ResultStr, 3, Length(ResultStr)-2);
//收到服务端信息
Form1.Memo2.Lines.Add(ResultStr);
//服务端返回值
ResultStr := 'R:'+ResultStr + '@' + ResultStr;
//
ClientSocket.SendText(ResultStr);
ClientSocket.Close;
//Terminate;
end;
end
else
begin
ClientSocket.Close;
Terminate;
end;
finally
Stream.Free;
end;
end;//while
except
ClientSocket.Close;
Terminate;
end;
end;
DLL动态库:
unit SockDM;
procedure Delay(dwMilliseconds: Longint); //延时
var
iStart, iStop: DWORD;
begin
iStart := GetTickCount;
repeat
iStop := GetTickCount;
until (iStop - iStart) >= dwMilliseconds;
end;
procedure TSDM.DataModuleCreate(Sender: TObject);
var
IniFile: TInifile;
begin
//取服务器IP地址、端口号
IniFile := TIniFile.Create('MyApp.ini');
try
ClientSocket.Address := IniFile.ReadString('RomterServer', 'Server', '');
ClientSocket.Port := IniFile.ReadInteger('RomterServer', 'Port', 0);
//
ClientSocket.Address := '127.0.0.1';
ClientSocket.Port := 1024;
finally
IniFile.Free;
end;
end;
//阻塞方式处理流程*******************************************************
Function TSDM.UnLoadMsg(Msg: String; ctClientType: TClientType): String;
var
TimeBegin, Time: DWORD; //起始时间
TimeOut: Integer; //超时阀值
ResultStr: String; //返回处理
begin
//客户端连接
ErrorNum := 0;
if ClientSocket.Active then ClientSocket.Active := False;
ClientSocket.Address := '127.0.0.1';
ClientSocket.Port := 1024;
ClientSocket.ClientType := ctClientType; //阻塞方式
ClientSocket.Open; //打开客户端连接
timeBegin := GetTickCount; //起始时间
while True do
begin
//判断网络连接成功
if not ClientSocket.Socket.Connected then
begin
ClientSocket.Active := True;
Continue;
end;
//字符上传,加发送标识(S
ClientSocket.Socket.SendStream(TStringStream.Create('S:'+Msg)); //上传数据(数据流方式)
if ErrorNum > 5 then
begin
Result := '-10001|系统错误,可能是服务端没有启动!';
Break; //系统错误,不能返回值
end;
if ClientSocket.ClientType = ctBlocking then //阻塞方法需要主动去读
begin
ReadStr := ClientSocket.Socket.ReceiveText;
end;
if LeftStr(ReadStr, 2) = 'R:' then //根据返回值信息标识
begin
//已经收到数据, 非阻塞方式数据由OnRead事件触发
Result := Copy(ReadStr, 3, Length(ReadStr)-2); //返回时去标识号
Break;
end;
//是否超时处理
Time := GetTickCount;
if Time-TimeBegin >= 6000 then
begin
//网络超时
Result := '-10001|网络超时错误!';
Break;
end
else
begin
//延时100微妙
Delay(100);
end;
end;
end;
procedure TSDM.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
begin
ReadStr := Socket.ReceiveText;
end;
procedure TSDM.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Inc(ErrorNum);
ErrorCode := 0;
//写客户端连接错误日志
end;
上面处理也可以通/
但存在下面几个问题:
1、客户端连接后怎么还是Conneted = False
2、服务端在数据传输后立即关掉了
3、传输中存在乱码
4、怎么没有说如何创建流套接字?
5、SendText与SendStream有什么区别?
有没有用Delphi做过SOCKET.通讯的?