如何在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;



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


}
}

...全文
1210 22 打赏 收藏 转发到动态 举报
写回复
用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)
代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制与早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置与故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单中增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单中已有的项目。 bootcfg /disableredirect 在启动引导程序中禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...

18,356

社区成员

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

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