如何在socket发送完成后立即关闭socket?

BaoBrother 2010-02-11 07:21:25
本新手,处于学习过程中,如题,该问题困扰了我很久,至今终于没能真正的解决。

send(s,str,strlen(str),0);
closesocket(s);

if(send(s,str,strlen(str),0)>0)
{closesocket(s);}


如果按照以上的代码,可能会出现数据没发送完成就关闭了这个连接,客户端可能收不到或者收到不完整的数据。



补充说明一下,我用的是不是MFC框架,大概是SDK吧,看看如下程序:

//消息循环函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
... ...无关内容,略...


//网络消息
case WM_NETWORK:
switch (lParam)
{

//收到连接申请时接受连接
case FD_ACCEPT:
sAccept=accept(sListen,(struct sockaddr*)&cliet,&iLen);
//....
break;


//收到数据
case FD_READ:
//....
break;



疑问一:当数据发送完成后,这里是否会收到系统的通知消息???要是有就好办了,要是没有,怎么解决问题呢?多谢啦!


}
}

...全文
1128 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
BaoBrother 2010-02-18
  • 打赏
  • 举报
回复
谢谢各位,我心理有个底了,封贴!
BaoBrother 2010-02-17
  • 打赏
  • 举报
回复
好,谢谢,再学习学习!
UDX协议 2010-02-17
  • 打赏
  • 举报
回复
这要看2种情况。
1.阻塞模式。在这种情况下,当send返回时基本上可以认为对方已经 收到了数据。这里返回的就是长度。出错就另外处理。
2.非阻塞,情况比较复杂一些。就象以上其他人说的,因为发送是立即完成的,所以不能简单的认为对方已经收到,所以可以采用windows自己带的一些api去检测发送状态。比如wsawaitfor...,waitfor..,getoverlay...等,当这些值正确返回时可以得到已经传送的字节数,具体细节可以查看帮助。

从效率上来说,2更灵活,但是也更复杂,效率更高。这就是要考虑各位编程水平了。

但总的来说,不管是1,还是2,都还是存在一些特别情况,也就是并非万无一失的把数据发送给对方了。所 以在应用层加一些一个保证机制才是最重要的。

csl312211865 2010-02-16
  • 打赏
  • 举报
回复
再不行就让接收方收到数据后,给发送方发一个接受确认信息,发送方收到这个确认信息后,再关闭socket。
楼主要是想搞网络编程,还是系统的学习下计算机网络的相关知识。
csl312211865 2010-02-16
  • 打赏
  • 举报
回复
引用 14 楼 baobrother 的回复:
楼上的,不好啊,你应该看看8楼的说法。


引用 8 楼 wineggdrop 的回复:默认情况下,应用程序调用send(),数据只是被保存到系统的内核缓冲,但并不一定数据马上被发送出去的,如果这时侯调用closesocket(),那么数据可能就会在内核缓冲被发送出去前就因为closesocket()而被抹掉。
那请问怎么知道数据到底是发送出去,还是一直被留在缓冲区内?不能判断的话,那你是不是永远都不要关闭这个socket?进而永远别关电脑了?你就一直等着吧。。。你这一生就等着吧。。。
楼主不要鸡蛋里挑骨头了,拿代码去调试下。传输文件的时候,都是用这种循环来保证发送指定大小的。
csl312211865 2010-02-16
  • 打赏
  • 举报
回复
引用 17 楼 baobrother 的回复:
首先,我可以对天发誓,我并不是要在鸡蛋里挑骨头,我的程序是服务器端程序,提供多客户端访问资源的,一但访问完了,收到了相应的数据后,理当关闭这个连接并释放资源,所以想请教大家有什么更好的办法,或者说跟大家交流一下(不好意思,高攀了),尽量采用一种更完美的方式解决问题。
为什么说你鸡蛋里挑骨头?数据能不能准确无误的发送给对方,那是TCP/IP协议所关心的事,而不是网络编程者所该关心的。你用TCP/IP去发数据,TCP/IP协议告诉你(即send的返回值),数据发出去了,那就是发出去了,告诉你没发出去,那就是没发出去。所以让你去系统的学学计算机网络。
luck_wei 2010-02-16
  • 打赏
  • 举报
回复
lz:
1、流式套接字是可靠的(这是协议决定的),所以send的返回确实是发送的字节数。换句话就是客户端确实已经收到了这么多数据。
2、一般发送的数据小于1k总是会正常发送的。
3、当你发送的数据量比较大时就需要使用循环发送的方法保证所有数据已经发送完全,方法就是13楼所展示的。

另外:你是初学者我也是,大家一起进步。

最近我正在翻译一份网络程序设计方面的资料(很基础),大家有兴趣可以去看看(就在我的空间里)。这是第一篇的连接:http://blog.csdn.net/luck_wei/archive/2010/02/14/5308635.aspx地址。
BaoBrother 2010-02-16
  • 打赏
  • 举报
回复
引用 15 楼 csl312211865 的回复:
那请问怎么知道数据到底是发送出去,还是一直被留在缓冲区内?不能判断的话,那你是不是永远都不要关闭这个socket?进而永远别关电脑了?你就一直等着吧。。。你这一生就等着吧。。。
楼主不要鸡蛋里挑骨头了,拿代码去调试下。传输文件的时候,都是用这种循环来保证发送指定大小的。


首先,我可以对天发誓,我并不是要在鸡蛋里挑骨头,我的程序是服务器端程序,提供多客户端访问资源的,一但访问完了,收到了相应的数据后,理当关闭这个连接并释放资源,所以想请教大家有什么更好的办法,或者说跟大家交流一下(不好意思,高攀了),尽量采用一种更完美的方式解决问题。

至于学习网络相关的知识,我会的慢慢学的,谢谢你的关心,学无止境,边做边学吧!~


最后,不好意思,思想开点小差,斗胆试问一下:这是你的真实头像吗?你的头像也太勾人了吧,哈哈!~~有机会我们认识认识 :) (是美女的话)

BaoBrother 2010-02-16
  • 打赏
  • 举报
回复
楼上的,不好啊,你应该看看8楼的说法。


引用 8 楼 wineggdrop 的回复:默认情况下,应用程序调用send(),数据只是被保存到系统的内核缓冲,但并不一定数据马上被发送出去的,如果这时侯调用closesocket(),那么数据可能就会在内核缓冲被发送出去前就因为closesocket()而被抹掉。
csl312211865 2010-02-15
  • 打赏
  • 举报
回复
给你一个保证能发送指定大小函数吧
int sendn(SOCKET fd,char *bp,int len)
{
int cnt;
int rc;
cnt=len;//要发送的字节数,即Length of the data in buf.
//用下面的这个while循环来保证,要发送的数据全部都被发送出去了。
while(cnt>0)
{
rc=send(fd,bp,cnt,0);
if(rc<0)
{
CString aaa;
aaa="发送错误\n";
// AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
aaa.ReleaseBuffer();
return -1;
}
if(rc==0)
return len-cnt;
//发送完一批数据后,缓冲区指针要改变,
bp+=rc;
//Length of the data in buf也要变。
cnt-=rc;
}
return len;
}
BaoBrother 2010-02-15
  • 打赏
  • 举报
回复
int bufferLen= 0;
if(setsockopt(s,SOL_SOCKET,SO_SNDBUF,(char *)&bufferLen,sizeof(bufferLen))<0)
{
return;
}
BaoBrother 2010-02-15
  • 打赏
  • 举报
回复
引用 8 楼 wineggdrop 的回复:
默认情况下,应用程序调用send(),数据只是被保存到系统的内核缓冲,但并不一定数据马上被发送出去的,如果这时侯调用closesocket(),那么数据可能就会在内核缓冲被发送出去前就因为closesocket()而被抹掉。如果要发送的数据不大,那么可以将socket的发送缓冲设置为0,那么发送的数据就并不是发送到系统内核缓冲,而是马上发向目标,通过send()返回值,就知道是否发送成功,如果成功?-


怎样将socket的发送缓冲设置为0?不好意思,做好事做到底吧(呵呵),不是我懒不查资料,而是不想走太多弯路。
BaoBrother 2010-02-15
  • 打赏
  • 举报
回复
问题还没解决,谁还有什么高见吗?
BaoBrother 2010-02-12
  • 打赏
  • 举报
回复
难道真的没办法了吗,别让我绝望,大家帮帮忙!...
sjdev 2010-02-12
  • 打赏
  • 举报
回复
up
WinEggDrop 2010-02-12
  • 打赏
  • 举报
回复
默认情况下,应用程序调用send(),数据只是被保存到系统的内核缓冲,但并不一定数据马上被发送出去的,如果这时侯调用closesocket(),那么数据可能就会在内核缓冲被发送出去前就因为closesocket()而被抹掉。如果要发送的数据不大,那么可以将socket的发送缓冲设置为0,那么发送的数据就并不是发送到系统内核缓冲,而是马上发向目标,通过send()返回值,就知道是否发送成功,如果成功,那么就可能调用closesocket()了。
BaoBrother 2010-02-11
  • 打赏
  • 举报
回复
我的程序不能实现对方发送回应,只有服务端,客户端是Windos应用程序。
Conry 2010-02-11
  • 打赏
  • 举报
回复
如果一定要确认的话,最好还是等对方发送回应才能真正算是收到
dd_zhouqian 2010-02-11
  • 打赏
  • 举报
回复
if(send(s,str,strlen(str),0)==strlen(str))
{closesocket(s);}

或者循环发送,每次发送成功后累计,直到等于要发送的字节数
stjay 2010-02-11
  • 打赏
  • 举报
回复
send后closesocket
查找关键词setsockopt SO_LINGER

疑问一:当数据发送完成后,这里是否会收到系统的通知消息???要是有就好办了,要是没有,怎么解决问题呢?多谢啦!

可考虑用WSAEventSelect模型
加载更多回复(2)
完成端口通讯服务器(IOCP Socket Server)设计 (六)功能强大的IOCP Socket Servre模块例程源码 Copyright © 2009 代码客(卢益贵)版权所有 QQ:48092788 源码博客:http://blog.csdn.net/guestcode 一、声明 版权声明: 1、通讯模块代码版权归作者所有; 2、未经许可不得全部或部分用于任何项目开发; 3、未经许可不得部分修改后再利用源码。 免责声明: 1、 由于设计缺陷或其它Bug造成的后果,作者不承担责任; 2、未经许可的使用作者不提供任何技术支持服务。 权利和义务: 1、任何获得源码并发现Bug的个人或单位均有义务向作者反映; 2、作者保留追究侵权者法律责任的权利。 二、开发背景 部分代码由前项目分离而来,尚未有应用考验,但对于初学者学习和进阶有很大帮助。性能上尚未有定论,但应该不会令你失望。 三、功能说明 1、可以关闭Socket的Buffer; 2、可以关闭MTU(不等待MTU满才发送); 3、可以多IP或多端口监听; 4、可以重用socket(主动关闭除外); 5、可以0缓冲接收(Socket的Buffe = 0时,避免过多的锁定内存页); 6、可以0缓冲连接(客户端仅连接,不一定立即发数据); 7、可以条件编译: a、是否使用内核Singly-linked lists; b、是否使用处理线程(工作线程和处理线程分开); c、是否使用内核锁来同步链表。 8、可以实现集群服务器模式的通讯(有客户端socket); 9、可以单独设置每个连接的Data项来实现连接和Usernfo的关联; 10、每个线程有OnBegin和OnEnd,用于设置线程独立的对象(数据库会话对象); 11、可以提供详细的运行情况,便于了解IOCP下的机制,以及进行调试分析; 12、可以发起巨量连接和数据(需要硬件配置来支持)。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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