异步SOCKET编程-发送和接收数据

转载 2006年05月18日 10:06:00

原作者:DREWSIKORA

我本想把发送和接收分开作为两部分,但是最后我决定只略微解释一下FD_READ,留下更多的时间来说 明更复杂的FD_WRITE,FD_READ事件非常容易掌握.当有数据发送过来时,WinSock会以FD_READ事件通知你,对于每一个 FD_READ事件,你需要像下面这样调用recv():

intbytes_recv=recv(wParam,&data,sizeof(data),0);

基 本上就是这样,别忘了修改上面的wParam.还有,不一定每一次调用recv()都会接收到一个完整的数据包,因为数据可能不会一次性全部发送过来.所 以在开始处理接收到的数据之前,最好对接收到的字节数(即recv()的返回值)进行判断,看看是否收到的是一个完整的数据包.

FD_WRITE相对来说就麻烦一些.首先,当你建立了一个连接时,会产生一个FD_WRITE事件.但是如果你认为在收到FD_WRITE时调用send()就万事大吉,那就错了.FD_WRITE事件只在发送缓冲区有多出的空位,可以容纳需要发送的数据时才会触发.

上 面所谓的发送缓冲区,是指系统底层提供的缓冲区.send()先将数据写入到发送缓冲区中,然后通过网络发送到接收端.你或许会想,只要不把发送缓冲区填 满,让发送缓冲区保持足够多的空位容纳需要发送的数据,那么你就会源源不断地收到FD_WRITE事件了.嘿嘿,错了.上面只是说FD_WRITE事件在 发送缓冲区有多出的空位时会触发,但不是在有足够的空位时触发,就是说你得先把发送缓冲区填满.

通常的办法是在一个无限循环中不断的发送数 据,直到把发送缓冲区填满.当发送缓冲区被填满后,send()将会返回SOCKET_ERROR,WSAGetLastError()会返回 WSAWOULDBLOCK.如果当前这个SOCKET处于阻塞(同步)模式,程序会一直等待直到发送缓冲区空出位置然后发送数据;如果SOCKET是非 阻塞(异步)的,那么你就会得到WSAWOULDBLOCK错误.于是只要我们首先循环调用send()直到发送缓冲区被填满,然后当缓冲区空出位置来的 时候,系统就会发出FD_WRITE事件.有没有想过我能指出这一点来是多么不容易,你可真走运.下面是一个处理FD_WRITE事件的例子.

caseFD_WRITE: //可以发送数据了
 {
   //进入无限循环
   while(TRUE)
   {
     //从文件中读取数据,保存到packet.data里面.
     in.read((char*)&packet.data,MAX_PACKET_SIZE);

     //发送数据
     if(send(wparam,(char*)(&packet),sizeof(PACKET),0)==SOCKET_ERROR)
     {
       if(WSAGetLastError()==WSAEWOULDBLOCK)
       {
         //发送缓冲区已经满了,退出循环.
         break;
       }
       else//其他错误
       {
         //显示出错信息然后退出.
         CleanUp();
         return(0);
       }
     }
   }
 }break;

看到了吧,实现其实一点也不困难.你只是弄混了一些概念而已.使用这样的发送方式,在发送缓冲区变满的时候就可以退出循环.然后,当缓冲区空出位置来的时候,系统会触发另外一个FD_WRITE事件,于是你就可以继续发送数据了.

在 你开始使用新学到的知识之前,我还想说明一下FD_WRITE事件的使用时机.如果你不是一次性发送大批量的数据的话,就别想着使用FD_WRITE事件 了,原因很简单-如果你寄期望于在收到FD_WRITE事件时发送数据,但是却又不能发送足够的数据填满发送缓冲区,那么你就只能收到连接刚刚建立时触发 的那一次FD_WRITE-系统不会触发更多的FD_WRITE了.所以当你只是发送尽可能少的数据的时候,就忘掉FD_WRITE机制吧,在任何你想发 送数据的时候直接调用send().

结论

这是我在GOOGLE上搜到的一篇文章中的一部分.虽然原作者的 部分观点似乎并不正确,但是文章写得很易懂.其实,如果你想收到FD_WRITE  事件而你又无法先填满发送缓冲区,可以调用 WSAAsyncSelect(...,FD_WRITE).如果当前发送缓冲区有空位,系统会马上给你发FD_WRITE事件.

FD_WRITE消息,MFC的CAsyncSocket类将其映射为OnSend()函数.FD_READ消息,被映射为OnReceive()函数.

C#中异步SOCKET发送数据时内存问题

做CS的开发一直都是这样的方式: server端用 C++编写,采用IOCP机制处理大量客户端连接、数据接收发送的问题 client端用 C++ 或C# 写,没什么特殊要求。 ...
  • daihongshu
  • daihongshu
  • 2014年05月14日 16:23
  • 1604

C#中Socket通信编程的异步实现

本文将在C#中Socket同步通信的基础上,分析和研究Socket异步编程的实现方法,目的是深入了解Socket编程的基本原理,增强对网络游戏开发相关内容的认识。什么是Socket编程的异步是实现所谓...
  • qinyuanpei
  • qinyuanpei
  • 2015年03月23日 21:36
  • 5912

Java Socket编程(四) 异步服务器

基于Java Socket给出了异步服务器的实现
  • yjp19871013
  • yjp19871013
  • 2016年12月14日 10:26
  • 2158

Socket编程(异步通讯)(Tcp,Udp)

上一章主要展示了Socket的Tcp\Udp两种协议下的基本通讯方式,属于同步通讯。至于一个服务器对应多个客户端,或者对应多个请求,我们采用的是多线程的方式来解决此问题。然而本章节我们将有更好的方式去...
  • CNHK1225
  • CNHK1225
  • 2016年12月17日 15:14
  • 1944

Socket层实现系列 — 信号驱动的异步等待

主要内容:Socket的异步通知机制。 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd   概述   socket上定义了几个IO事件:状态改变事件、有数...
  • zhangskd
  • zhangskd
  • 2015年05月23日 22:24
  • 4392

Socket异步发送接收,Windows

vdAsynSocket.h: //////////////////////////////////////////////////////////////// // //Descript:...
  • kanguolaikanguolaik
  • kanguolaikanguolaik
  • 2013年05月23日 09:46
  • 966

C#:简单的Socket异步通信功能(客户端)

上一篇(http://www.rexcao.net/archives/159)讲了服务端使用Socket发送消息的方法,这一篇来解决一下客户端如何接收服务端消息的问题。 目标 1、异步接收...
  • jsjpanxiaoyu
  • jsjpanxiaoyu
  • 2016年10月28日 13:07
  • 2029

c++ socket 异步编程

在网络通讯中,由于网络拥挤或一次发送的数据量过大等原因,经常会发生交换的数据在短时间内不能传送完,收发数据的函数因此不能返回,这种现象叫做阻塞。 Winsock对有可能阻塞的函数提供了两种处理方式:阻...
  • u010178308
  • u010178308
  • 2017年04月24日 07:57
  • 670

C++ socket编程基础三(Windows异步套接字)

异步套接字: 如果使用阻塞的套接字的话,在控制台下还好!如果是WIN32程序的话,那么就容易造成界面的假死,因为接收函数一直等待有消息进来之后才会被返回!所以此时界面一直属于假死的状态,如果你乱动的...
  • zh13544539220
  • zh13544539220
  • 2015年04月03日 10:48
  • 3328

异步SOCKET与同步SOCKET

Windows套接字在两种模式下执行I/O操作,阻塞和非阻塞。在阻塞模式下,在I/O操作完成前,执行操作的Winsock函数会一直等待下去,不会立即返回程序(将控制权交还给程序)。而在非阻塞模式下,W...
  • baidu_19340981
  • baidu_19340981
  • 2014年09月16日 14:42
  • 2015
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:异步SOCKET编程-发送和接收数据
举报原因:
原因补充:

(最多只允许输入30个字)