2000分求教WINSOCK问题。(200分)

  • 主题发起人 主题发起人 Lizqin
  • 开始时间 开始时间
L

Lizqin

Unregistered / Unconfirmed
GUEST, unregistred user!
一:采用TCP协议连接。SERVER 端负责转发多个 CLIENT 的消息,但由于某些 CLIENT 是
拨号接入互联网,偶尔会出现断线现象,此时 SERVER 无法及时响应此 CLIENT 已断开,
且没有任何错误信息。请问,我该如何处理?

二:求 TCP & UDP 使用 SOCK5 (含验证模式)代理的完整可编译演示代码及说明文档。



如您能回答该问题,请一并告知如何支付2000分数。
 
我有一本叫WINSOCK规范的电子书,不知对你有用不?
 
1.if 没有任何错误信息 is true then 可以采用石器时代的做法:让客户端自动定时(1s?)向
服务端发送1Byte的信息,若服务端连续若干秒都没有收到某个客户端的信息,则可以认为客户
端已经断开,并在服务器端执行相应的断开操作。考虑到由于网络拥挤时产生的延迟和丢包
现象,确认断开时间因该在分钟级。
 
Lear,如果不麻烦的话,请邮寄到 q.yuhen@china.com。谢谢!分数等问题结束时送上。

creation-zy,你的想法可行,可问题是服务端的转发是实时性的,您的做法会出现如下
问题:
1.延时 2.消息丢失。
 
服务器端可以采用NETSTAT命令检查本地端口状态的原理来定时检查本地的
SOCKET接口状态

附:NETSTAT TCP套接字解释
CLOSED 没有使用这个套接字
LISTEN 套接字正在监听入境连接
SYN_SENT 套接字正在试图主动建立连接
SYN_RECEIVED 正在处于连接的初始同步状态
ESTABLISHED 连接已建立
CLOSE_WAIT 远程套接字已经关闭:正在等待关闭这个套接字
FIN_WAIT_1 套接字已关闭,正在关闭连接
CLOSING 套接字已关闭,远程套接字正在关闭,暂时挂起关闭确认
LAST_ACK 远程套接字已,正在等待本地套接字的关闭确认
FIN_WAIT_2 套接字已关闭,正在等待远程套接字关闭
TIME_WAIT 这个套接字已经关闭,正在等待远程套接字的关闭传送
 
不是吧...
我所说的延迟和丢包现象都是由网络硬件造成的,并非服务程序的错。我上面提到的方法仅当
客户端发生断线以后才会奏效,此方法本身不会使客户端与服务器的正常通信收到任何影响。
服务器所要做的只是用一个Timer定时检查各个客户端的无响应时间,如果超过规定的时间,
就主动断开连接,收回相应资源。而在此期间,客户端有可能已经再次连接到服务器——当然
它们所占用的Connection不会一样,所以不会发生将重新连入的客户端踢出的现象。

参考一下联众的方法——它正是通过每秒钟发出一个走时信息与客户端保持联络的,一旦客户端
超过300秒没有应答,则认为此玩家已经退出游戏。若客户端在此期间又重新连入了游戏,服务
端则通过玩家发出的的ID信息让它继续原来的游戏。
——我想不出比他更高明的办法了。
 
creation-zy:

我指的信息丢失是指:
?当某个客户刚提交走时信息后发生中断,此时恰有消息需转发给该客户端。
由于此动作发生在判断超时动作之前,则此信息无法转发而造成丢失。
谢谢!

wys205:
NETSTAT是个命令行程序,请问在程序总如何接收其反馈信息。谢谢!

Lera:
您的电子书我已收到,谢谢!
 
1,加信道检测代码
2,没有,只有老的Socket 2的代码。
 
这个好办,有几种解决方案:
1.让客户端每次收到应答信息之后发出一个确认接收信号——不过,TCP/IP协议是可靠连接,这个
功能在协议内部已经实现,我觉得如果向一个已经断开连接的客户端发出信息的话,应该产生发送
失败错误。由于我这里没有办法试验,所以还不能肯定在这种情况下一定能够产生错误。
2.让客户端再次连入的时候将请求重新发送一遍

还有一点我不太明白——就算服务端能够立刻检测到客户端的断开,这个将要被发送的信息又有
什么用呢?——它无论如何都不可能让客户端在第一时间内接收到了。可能的解决方案是:
服务端将每个客户的最后一次应答信息保存起来,一旦在某次应答之后,客户端断线了,那么,
在客户端重新连入服务端的时候,会向服务端发出一个请求上一次应答的信号(客户端显然知道
自己的请求有没有得到应答),这样,服务端就会将上一次的应答信息再次发送给客户端。如果
这一次发送也失败了,客户端下次连入时就会再次重复上述过程,直到得到应答为止。
 
各位的方法我都进行了测试。效果不太理想。
不过,我想也只能这样了。

烦请各位告知2000分如何支付?
 
NETSTAT是个命令行程序,可以在程序中将其执行结果写入文本文件,
再从文件中读出即可.

 
再次打扰各位。烦请各位告知2000分如何支付?
 
对不起!很长时间没上。抱歉!
 
UDP的Sock5我好像写过,要的话我可以找一下。
 
我也在做,好像不太好用,哪位指导一下!
 
我是菜鸟,我是这样处理的[:D]
procedure TDataServerThread.Execute;
var
Buffer : array[0 .. Buffer_length] of Char;
i:integer;
begin
pub_Edit_Recorder_count:=0;
pub_Insert_Recorder_count:=0;
Pub_FieldsList := TStringList.Create; //表头
fm_Main.UserCount.Caption:=IntToStr(StrToInt(fm_Main.UserCount.Caption)+1);
while not Terminated and ClientSocket.Connected do //线程循环,除非线程终止或客户断连接
try
pub_Stream := TWinSocketStream.Create(ClientSocket, 60000);
FillChar(Buffer, Buffer_length, 0);
i:=0;
try
if pub_Stream.WaitForData(WateFor_Time) then //等待WateFor_Time秒,读取数据。
begin
try
i:=Pub_Stream.Read(Buffer, Buffer_length);
except
Pub_LogStr:='不能读该用户数据,该用户可能已经断线了。';
Synchronize(WriteLog);
ClientSocket.Close;
end;
if i > 0 then { 如果能在WateFor_Time秒里读到数据 }
begin
try
ProcessTheRequest(Buffer) //自定义过程处理用户请求
except
pub_Logstr:='无名错误!!!';
Synchronize(WriteLog);
end;
end
else
ClientSocket.Close; { 关闭客户端连接}
end
else
ClientSocket.Close; { 60秒钟如客户无响应,KILL他的连接 }
finally
Pub_Stream.Free;
end;
except
HandleException;
Pub_FieldsList.Free;
end;
Pub_LogStr:='修改记录:'+Inttostr(pub_Edit_Recorder_count)+' 条,新增记录:'+Inttostr(pub_Insert_Recorder_count)+'条。';
Synchronize(WriteLog);
end;
 
http://tangentsoft.net/wskfaq/
 
多人接受答案了。
 
后退
顶部