我用clientsocket控件 写了一个客户端程序,定时向客户端发送当前时间的字符串
用serverSocket控件 写了一个服务器程序,接收到客户端的数据后,把数据原样发送回去。我打开了10个左右的客户端程序,每隔1秒,向服务器发送数据,服务器收到后,发送回来。经过测试发现以下问题:1.clientsocket 客户端 有时会无端断开。
2.serversocket 服务器端 测试一个上午后,出现问题。客户端发送的数据,部分没有返回,有的几条数据一起返回(这个应该是网络问题)3.serversocket 服务器端 显示的连接数不准确,我所有客户端连接断开后,仍然显示有62个连接
4.serversocket 服务器端 最严重的问题,服务器端运行了一天,第二天客户端连接时连接不上了。我把程序贴出来,请高手指点,谢谢先。
用serverSocket控件 写了一个服务器程序,接收到客户端的数据后,把数据原样发送回去。我打开了10个左右的客户端程序,每隔1秒,向服务器发送数据,服务器收到后,发送回来。经过测试发现以下问题:1.clientsocket 客户端 有时会无端断开。
2.serversocket 服务器端 测试一个上午后,出现问题。客户端发送的数据,部分没有返回,有的几条数据一起返回(这个应该是网络问题)3.serversocket 服务器端 显示的连接数不准确,我所有客户端连接断开后,仍然显示有62个连接
4.serversocket 服务器端 最严重的问题,服务器端运行了一天,第二天客户端连接时连接不上了。我把程序贴出来,请高手指点,谢谢先。
procedure TForm1.runClick(Sender: TObject);
begin
ServerSocket1.Port := StrToInt(Edit1.Text); //设置端口号
if ComboBox1.ItemIndex = 0 then
ServerSocket1.ServerType := stThreadBlocking //实际未用
else
ServerSocket1.ServerType := stNonBlocking; //异步方式
try
ServerSocket1.Active := True;
except
end;
run.Enabled := False;
stop.Enabled := True;
end;//停止程序
procedure TForm1.stopClick(Sender: TObject);
begin
ServerSocket1.Active := False;
run.Enabled := True;
stop.Enabled := False;
end;
//连接上程序
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
//判断连接数
StatusBar1.SimpleText := 'connections '+ IntToStr(serversocket1.Socket.ActiveConnections);
Timer1.Interval := 100; //100ms
Timer1.Enabled := True; //定时
end;
//断开程序
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'connectioss '+ IntToStr(serversocket1.Socket.ActiveConnections);
end;//接收 读数据程序 并发送
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
str1 : string;
i : integer;
begin
str1 := Socket.ReceiveText;
Memo1.Lines.Add(str1);
Edit2.Text := IntToStr(StrToInt(Edit2.Text)+1);
if StrToInt(Edit2.Text) > 200 then
memo1.Lines.Delete(0); //删除最早的一条
//判断是哪一路的连接
for i:=0 to serversocket1.Socket.ActiveConnections-1 do
if serversocket1.Socket.Connections[i].sockethandle=socket.SocketHandle then
begin
serversocket1.Socket.Connections[i].SendText(str1); //发送接收的字符串
break;
end;
end;
2.有可能是因为在处理消息过程当中更新了UI导致消息重入或者丢失而遗漏;另外就是流协议的本质,会存在断包和粘包现象,属于正常的,建议在发送的时候使用定长数据,或者由前置的一小段定长数据(比如一个四字节或两字节的数据)表示或提示后续内容的长度,从而在接收端加以处理,然后对断包进行拼接,对粘包进行分割;
3.还是可能因为消息丢失而导致的问题,当然也有可能是因为连接并没有真正断开(可以使用netstat -na -o)查看socket状态;
4.分为两种情况,首先要找出是客户端无法连接服务器,还是服务器不接受客户端的连接;前者应该是类似问题3所说的情况,可以重启客户端机器或者换一台客户端机器测试一下,用于确认;如果是服务器出现问题,则有可能是服务器资源被消耗完了,应该可以用任务管理器看到服务器的内存使用状态,特别是未分页内存(核心内存)占用是不是过高(Win32平台极限值只有256MB).
我觉得很大
参考一下这段代码 client_record = Record
CHandle: integer;
CSocket:TCustomWinSocket;
CName:string;
CAddress:string;
CUsed: boolean; //是否被使用
session:array[0..CMax] of client_record; //定义一个记录型数组procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i,j,n,k:integer;
sAConnections:TConnectionsParam;
begin
connectok:=true;
j:=-1;
for i:=0 to sessions do
begin
if not session[i].CUsed then
begin
session[i].CHandle:=socket.SocketHandle;
session[i].CSocket:=socket;
session[i].CName:=socket.RemoteHost;
session[i].CAddress:=socket.RemoteAddress;
session[i].CUsed:=true;
Break;
end;
j:=i;
end;
if j=sessions then
begin
inc(sessions);
n:=sessions;
session[n].CHandle:=socket.SocketHandle;
session[n].CSocket:=socket;
session[n].CName:=socket.RemoteHost;
session[n].CAddress:=socket.RemoteAddress;
session[n].CUsed:=True;
end;
end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i:=0 to sessions do
begin
if session[i].CHandle=socket.SocketHandle then
begin
session[i].CHandle:=0;
session[i].CUsed:=false;
break;
end;
end;
end;
谢谢您的回复!
1.对于您说的UI问题,在程序中应该怎么避免这种情况,从我给的程序中可以看出这种隐患吗?
2.客户端非正常关机(下班时,一台机器被我非正常关了),导致网络中断,服务器端 serversocket1.Socket.ActiveConnections 会正常反应吗?
如果不能,有什么办法可以让服务器端知道断开了。
3.(可以使用netstat -na -o)查看socket状态
见笑了,我不知道怎么看,netstat -na -o 在哪里看?
看了你给的代码,很不错的思路。但我的代码并没错啊,我的应用很简单,接收到直接原样发回去。没必要记录下来哪个client端连接。谢谢大家的回复。
NetStart是个命令行执行程序
跟Dos似的
2.客户端非正常关机(下班时,一台机器被我非正常关了),导致网络中断,服务器端 serversocket1.Socket.ActiveConnections 会正常反应吗?
如果不能,有什么办法可以让服务器端知道断开了。