TCP高手请进

runrunrun 2001-11-20 09:43:11
最近编一个网络程序,基于TCP协议的,用客户机去连服务器。客户机的本机端口固定为5000。
在客户机程序退出后,再启动一次,则报错:网络地址被占用(10048)。
用netstat查看,发现端口5000处于 TIME_WAIT 状态,要过好几分钟才释放。
不知在关闭套节字时有错,还是TCP协议本来就如此。
...全文
185 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
coolfired 2001-11-26
  • 打赏
  • 举报
回复
smallfool的话实际我已写了,你没细看,如下:
若是使用者原先设定此 Socket 为 SO_LINGER,则有两种情况:
(a) Timeout 设为 0 的话,此一 Socket 马上重新设定 (reset),未传完或未收到的
资料全部遗失。
(b) Timeout 不为 0 的话,则会将资料送完,或是等到 Timeout 发生後才真正关
闭。
程式结束前,千万别忘了要呼叫 WSACleanup() 来通知 Winsock
Stack;如果您不呼叫此一函式,Winsock Stack 中有些资源可能仍会被您占用而无
法清除释放.看MSDN:
setsockopt
The Windows Sockets setsockopt function sets a socket option.

int setsockopt (
SOCKET s,
int level,
int optname,
const char FAR * optval,
int optlen
);

SO_LINGER struct LINGER Linger on close if unsent data is present.
To enable SO_LINGER, the application should set l_onoff to a nonzero value, set l_linger to zero or the desired time-out (in seconds), and call setsockopt. To enable SO_DONTLINGER (that is, disable SO_LINGER) l_onoff should be set to zero and setsockopt should be called. Note that enabling SO_LINGER with a nonzero time-out on a nonblocking socket is not recommended.
Enabling SO_LINGER also disables SO_DONTLINGER, and vice versa. Note that if SO_DONTLINGER is DISABLED (that is, SO_LINGER is ENABLED) then no time-out value is specified. In this case, the time-out used is implementation dependent. If a previous time-out has been established for a socket (by enabling SO_LINGER), then this time-out value should be reinstated by the service provider.
实际上MSDN是最好的文档,多翻翻,有好处。
runrunrun 2001-11-22
  • 打赏
  • 举报
回复
ShutDown函数可以触发OnClose,我试过可以的。
你的OnClose是哪个套节字的?是监听套节字还是连接套节字?

我试了coolfired提供的方法,WSACleanup,还是不行。
smallfool的方法是可以的。
unix123 2001-11-22
  • 打赏
  • 举报
回复
ShutDown函数可以触发OnClose()吗,我试验过好象不行的
关于Accept套接字的问题,应该没有什么问题的,因为我把断点设置为OnClose函数中了呀
是不是有什么参数有问题呢
unix123 2001-11-21
  • 打赏
  • 举报
回复
我也涉及到关闭TCP/IP连接的问题,希望和大家讨论!

我如何断开TCP/IP的连接呢,我使用了Close(),但我发现Server端并没有触发OnClose()事件
我在Client和Server端Create Socket时做出以下修改
Client: Create(.....,FD_CONNECT|FD_CLOSE)
Serevr: Create(.....,FD_ACCEPT|FD_CLOSE)
也同样没有效果
同时我在删除Socket指针时出现共享错误,堆栈情况如下所示:
CAsyncSocket::KillSocket(unsigned int 444, CAsyncSocket * 0x00474420 {CAsyncSocket}) line 482 + 34 bytes
CAsyncSocket::Close() line 235
CAsyncSocket::~CAsyncSocket() line 376
不知道是什么原因?望指教!
Ashura 2001-11-21
  • 打赏
  • 举报
回复
你不能写服务器端?那用setsockopt()设置SO_LINGER吧,
smallfool写的很好了。
xtky_limi 2001-11-21
  • 打赏
  • 举报
回复
这个贴子很好!!
yoboo_yb 2001-11-21
  • 打赏
  • 举报
回复
套接字绑定到一个端口,如果两端的连接没有彻底断开,关闭套接字后,本地地址和端口号与套接字的绑定关系还要维持一段时间完成超时处理,这是系统对套接字的处理方式。
因此,原因是你在关闭本端程序之前,没有完成断开双方连接。所以,你在关闭套接字之前,应先完成断开连接的过程。
zhaoweidf 2001-11-21
  • 打赏
  • 举报
回复
我自己的看法,不用这吗做你可以用winsock2.0,SDK,来做,客户端自己发配端口,当客户端向SERVER发出联接时,SERVE就会监听到客户端的IP 和端口,
smallfool 2001-11-21
  • 打赏
  • 举报
回复
您需要强行关闭套接字.当然需要一个选项LINGER
代码如下:
LINGER ling;
ling.l_onoff = 1;
ling.l_linger = 0;
setsockopt(hSocket,SOL_SOCKET,SO_LINGER,&ling,sizeof(LINGER));

closesocket(hSocket)
coolfired 2001-11-21
  • 打赏
  • 举报
回复
closesocket():关闭某一Socket。
格 式: int PASCAL FAR closesocket( SOCKET s );
参 数: s Socket 的识别码
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是用来关闭某一 Socket。
若是使用者原先对要关闭之 Socket 设定 SO_DONTLINGER,则在呼叫此一函式
後,会马上回覆,但是此一 Sokcet 尚未传送完毕的资料会继续送完後才关闭。
若是使用者原先设定此 Socket 为 SO_LINGER,则有两种情况:
(a) Timeout 设为 0 的话,此一 Socket 马上重新设定 (reset),未传完或未收到的
资料全部遗失。
(b) Timeout 不为 0 的话,则会将资料送完,或是等到 Timeout 发生後才真正关
闭。
程式结束前,千万别忘了要呼叫 WSACleanup() 来通知 Winsock
Stack;如果您不呼叫此一函式,Winsock Stack 中有些资源可能仍会被您占用而无
法清除释放哟。

WSACleanup():结束 Windows Sockets DLL 的使用。
格 式: int PASCAL FAR WSACleanup( void );
参 数: 无
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 应用程式在使用 Windows Sockets DLL 时必须先呼叫
WSAStartup() 来向 Windows Sockets DLL 注册;当应用程式不再需要使用
Windows Sockets DLL 时,须呼叫此一函式来注销使用,以便释放其占用的资
源。

要确认完全释放,使用while循环直到返回值为0

如你是教育网,可访问我的工作机,查阅编程资料http://202.114.245.75/mhsguru/mhsguru.asp
对教育网开放。其它地方会很慢。



runrunrun 2001-11-21
  • 打赏
  • 举报
回复
当然,从服务器端主动断开连接是好的。可是服务程序不是我做的,我只能改客户程序。
hongyucn 2001-11-21
  • 打赏
  • 举报
回复
其实你可以把端口设为reuse,其实这不是操作系统的问题,是TCP/IP的问题,在Unix/Linux下也一样的!至今我还没有找到根本解决的办法
runrunrun 2001-11-21
  • 打赏
  • 举报
回复
谢谢楼上的答复。
但现在我觉得问题出在客户端。因为即使我把服务程序关闭后再启动客户程序,也报“网络地址被占用”错误。
我查了一下帮助,好象 setsockopt 中有一个选项 linger 可以控制关闭方式,但我还不知道该怎么用。
请大家继续帮助
hydnoahark 2001-11-21
  • 打赏
  • 举报
回复
你不要从客户端关闭联接。你从客户端发送一条退出信息给服务器,由服务器关闭联接试试
luou 2001-11-21
  • 打赏
  • 举报
回复
试试先用shutdonw,再closesocket
服务器为什么只认客户端的端口5000?
Ashura 2001-11-21
  • 打赏
  • 举报
回复
服务器端要重载OnClose(),这样可以得到客户端的断开消息。
ky640 2001-11-21
  • 打赏
  • 举报
回复
服务器端在客户端调用closesocket时,可用select检查到(或者在用WINDOWS的消息模型时,会收到消息)这个事件,然后调用closesocket(客户端socket),此时关闭的整个过程算是完结了。
runrunrun 2001-11-21
  • 打赏
  • 举报
回复
服务器端该怎么做?
我自已编的一个模拟服务器端的程序也是这样。
runrunrun 2001-11-21
  • 打赏
  • 举报
回复
谢谢。我试一下先。

unix123的问题我认为可能是如下原因:
服务器端有两个套节字,一个是监听套节字(暂时称为s1),在ACCEPT后,创建了第二个套节字(暂称为s2)。
在客户端Close后,触发的是s2的OnClose函数。你可能重载的是 s1.OnClose()。
另外,比较好的关闭方法是:
1. 客户端调 ShutDown 函数
2. 服务器端的Onclose事件被触发,服务器作一些清理工作,然后调Close关闭套节字
3. 客户端的 Onclose事件被触发,然后客户端关闭套节字。

希望和大家继续讨论。
ky640 2001-11-20
  • 打赏
  • 举报
回复
那你看一看closesocket的返回值,但更可能是tcp协议的在关闭时要经过三个过程造成的,因为服务器编得不好,没有及时关闭接收到客户端的套接字,造成这三个过程是靠超时来完成的。
加载更多回复(2)

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧