首页
社区
课程
招聘
[旧帖] 异步套接字编程只能在MFC中使用? 只用c++控制台程序可以异步套接字吗 0.00雪花
发表于: 2016-10-9 18:46 6554

[旧帖] 异步套接字编程只能在MFC中使用? 只用c++控制台程序可以异步套接字吗 0.00雪花

2016-10-9 18:46
6554
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
当然可以
2016-10-9 18:47
0
雪    币: 18
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
搜了一天都是MFC的 给个链接可以吗,,
2016-10-9 18:49
0
雪    币: 149
活跃值: (2618)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
推荐hp-socket
2016-10-9 18:59
0
雪    币: 962
活跃值: (1681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
libuv好用
2016-10-9 19:57
0
雪    币: 44
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
WSASend()----异步发送
描述:
在已建立连接的套接字上发送数据(支持重叠I/O)
int WSAAPI WSASend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

s:一个已经连接的套接字
lpBuffers:缓冲区结构数组(散播-聚集IO)
dwBufferCount:缓冲区结构数组的个数
lpNumberOfBytesSent:WSASend调用返回的指针里面包含了已发送的字节总数
dwFlags:一个标志,指定在其中调用了的方式。
lpOverlapped:重叠I/O结构
lpCompletionRoutine:异步I/O完成后的回调函数(完成例程)

注释:
WSASend覆盖标准的send函数,并在下面两个方面有所增强:
1、它可以用于overlapped socket(重叠socket)上以进行重叠发送的操作(简单地理解为就是异步send也可以了)
2、它可以一次发送多个缓冲区中的数据来进行集中写入。应该相当于unix上的writev,好处看来是避免Nagle算法。
WSASend用于在一个面向连接的套接字(第一个参数s)上发出的数据。

对于重叠套接字来说(通过WSASocket函数,用WSA_FLAG_OVERLAPPED标示创建的套接字), 发送消息时需要使用重叠IO结构(overlapped I/O),除非lpOverlapped与lpCompletionRoutine参数都是NULL。这时,这个套接字将被视为非重叠套接字。当所有的缓冲区都被发送完成了,将会执行一个动作来表示操作完成,这个动作可能是调用完成例程或者是引发一个event对象。如果操作没有立即完成, 最终的完成状态通过完成例程或者 WSAGetOverlappedResult得到。

对于非重叠套接字来说,最后两个参数lpOverlapped与lpCompletionRoutine被忽略(设置为NULL)时WSASend 与 send的功能相同。数据从用户缓冲区拷贝到发送缓冲区中(应该是指系统的套接字堆栈)。如果套接字是非阻塞且同时是面向流的(TCP),同时发送缓冲区没有足够的大小,WSASend将只发送用户缓冲区中的部分数据。如果同样的缓存大小而套接字是阻塞的,WSASend将阻塞直到用户所有的数据被发送成功。

lpBuffers这个参数是一个指针,它指向一个WSABUF结构的数组。这个数组可以是瞬态的(transient)。所谓瞬态的含义如下:如果这个操作是重叠的操作,服务提供者有责任在这个调用返回之前保存WSABUF数组。这允许用户的应用使用一个基于栈的WSABUF数组。就是说你可以定义一个局部变量,当WSASend返回后如果是重叠IO呢,你的函数局部变量已经被销毁了(例如你的函数已经返回了)。系统实际上还没发送数据呢,那你不要担心,系统会保存这个数组的副本。

对于面向消息的套接字(UDP), 不要超过下层协议的最大消息大小,这个值可以通过SO_MAX_MSG_SIZE这个套接字配置项得到。如果数据太长无法原子地发送,返回WSAEMSGSIZE, 数据没有发送成功。

dwFlags参数使用的标志与含义如下:
值        含义
MSG_DONTROUTE        指定的数据不应受制于路由。
MSG_OOB        发送带外数据,仅适用流套接字(SOCK_STREAM)
MSG_PARTIAL        指定lpBuffers只包含部分的信息。注意,返回的错误代码WSAEOPNOTSUPP将不支持部分消息传输的传输。

Overlapped Socket I/O
如果重叠操作立即完成,WSASend返回0 同时设置lpNumberOfBytesSent指向的变量为发送的字节数。如果重叠操作成功初始化将稍后完成,WSASend返回 SOCKET_ERROR同时设置错误码为WSA_IO_PENDING. 这时,lpNumberOfBytesSent指向的变量不会被更新。当重叠IO完成以后,发送的数量可以用两种方式取得:如果指定了完成例程(即lpCompletionRoutine),那么通过完成例程的cbTransferred参数得到。也可以调用WSAGetOverlappedResult函数通过lpcbTransfer参数得到。

WSASend可以在下列函数的完成例程中调用:WSARecv,WSARecvFrom,WSASend, 或WSASendTo. 这可以让时间敏感的数据传送得到更高的优先级(似乎也就是说你如果想让数据发得快一点,它就给你个机会快一点)。

在重叠操作期间,lpOverlapped指向的数据必须一直是合法的(你别弄些局部变量放进去)。如果同时有多个未决的IO操作,每一个操作必须有单独的WSAOVERLAPPED结构。

如果lpCompletionRoutine为空, 当操作完成时,如果lpOverlapped里面的hEvent是一个合法的event对象,系统会设置这个event为有信号(signaled )。用户的应用程序可以用WSAWaitForMultipleEvents或WSAGetOverlappedResult来等待这个事件。
如果lpCompletionRoutine非空,hEvent被忽略,它可以被用于传送上下文信息给完成例程。如果调用方设置了一个非空的lpCompletionRoutine随后又在同样的重叠IO上调用WSAGetOverlappedResult又没有设置WSAGetOverlappedResult 的参数为TRUE. 这时hEvent是未定义的,同时等待hEvent也将产生不预知的结果。(就是说你不要同时用完成例程和WSAGetOverlappedResult或者hevnet)。

这里的完成例程和windows文件IO的完成例程一样。一直到有线程处于alertable wait state状态时,完成例程才会被调用,例如调用WSAWaitForMultipleEvents并设置fAlertable为TRUE。

数据传送层(transport providers )允许用户在重叠套接字的完成例程里发出send和receive调用,同时保证对于一个给定的套接字,IO的完成例程不会嵌套。这可以让时间敏感的数据传送得到更高的优先级。

完成例程的原型如下:
void CALLBACK CompletionROUTINE(
  IN DWORD dwError,
  IN DWORD cbTransferred,
  IN LPWSAOVERLAPPED lpOverlapped,
  IN DWORD dwFlags
);
完成例程不过是用户定义的一个函数的占位符而已(就是说它是个回调函数)。
dwError:说明重叠IO完成的状态。
lpOverlapped:这个重叠IO由lWSASend函数的lpOverlapped参数指定
cbTransferred:是发送的字节数。
dwFlags:他总是被设为0。
该完成例程没有返回值。

如果你使用完成端口,要注意调用WSASend的次序就是就是缓冲区被填充的次序。不要从不同的线程中同时调用同一个socket上的WSASend函数,因为可能导致缓冲区中的数据处于不可预知的次序。

返回值:
函数成功:立刻返回0,否则返回SOCKET_ERROR。如果发生错误可以通过调用WSAGetLastError获取一个错误代码。如果错误代码是WSA_IO_PENDING表明重叠操作已成功启动,发送或接收操作将在稍后完成。

错误代码:
WSANOTINITIALISED:在调用本API之前应成功调用WSAStartup()
WSAENETDOWN:网络子系统失效
WSAEACCES:套接字连接广播地址失败,setsockopt的SO_BROADCAST未启用
WSAEINTR:通过WSACancelBlockingCall()函数取消(阻塞)调用
WSAEINPROGRESS:一个阻塞的Windows Sockets操作正在进行
WSAEFAULT:lpBuffers,lpNumberOfBytesSent,lpOverlapped,lpCompletionRoutine等                参数出错(这个错误一般是地址错误)
WSAENETRESET:连接已被打断,由于“keep-alive(心跳包)”出错
WSAENOBUFS:缓冲区死锁。
WSAENOTCONN:套接字未连接。
WSAENOTSOCK:s参数不是一个有效的套接字
WSAEOPNOTSUPP:MSG_OOB被指定,但是套接字不是流式的,如SOCK_STREAM类型
WSAESHUTDOWN:套接口已经关闭;一个套接口以SD_SEND或SD _BOTH的how参数                        shutdown()后,无法进行WSASend()调用。
WSAEWOULDBLOCK:重叠套接字:太多重叠的输入/输出请求。非重叠套接字:套                接口被标志为非阻塞,但是操作不能立即完成。
WSAEMSGSIZE:消息太大无法全部装入指定的缓冲区,故被修剪
WSAEINVAL:套接字未用bind()捆绑,或者套接字未用重叠标志创建
WSAECONNABORTED:虚拟电路被关闭由于超时或其他故障。
WSAECONNRESET:虚拟电路被远程端重置。
WSA_IO_PENDING:成功启动一个重叠操作,过后将有完成指示
WSA_OPERATION_ABORTED:重叠操作已经因为套接字被关闭而被取消或调用                                WSAIoctl函数执行SIO_FLUSH 命令
2016-10-9 20:52
0
雪    币: 44
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
WSARecv()-----异步接收
描述:
在已建立连接的套接字上接收数据
int WSAAPI WSARecv(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

s:一个已建立连接的套接字
lpBuffers:缓冲区结构数组(散播-聚集IO)
dwBufferCount:缓冲区结构数组的个数
lpNumberOfBytesRecvd:收到的字节数
lpFlags:函数工作方式(MSG_PEEK、MSG_OOB或MSG_PARTIAL)
lpOverlapped:重叠I/O结构
lpCompletionRoutine:异步I/O完成后的回调函数(完成例程)

注释:
WSARecv覆盖标准的recv函数,并在下面两个方面有所增强:
1、它可以用于重叠套接字(overlapped socket)上以进行重叠接收的操作(简单地理解为就是异步recv也可以了)
2、它可以一次接收多个缓冲区中的数据来进行集中组合。应该相当于unix上的writev,好处看来是避免Nagle算法。
3、lpFlags参数既是输入也是输出,允许程序设置MSG_PARTIAL、MSG_OOB、MSG_PARTIAL等标识位。MSG_PARTIAL标识不是所有协议都支持的。

WSARecv用于在一个面向连接的套接字(第一个参数s)上接收数据的。在服务器应用程序中,套接字通常通过bind函数进行显式的绑定本地地址或者通过隐式的accept函数WSAAccept函数绑定本地地址。在客户点应用程序中,套接字通过connect函数,WSAConnect函数,sento函数,WSASendTo函数或者WSAJoinLeaf函数隐式绑定本地地址。

对于重叠套接字来说(通过WSASocket函数,用WSA_FLAG_OVERLAPPED标示创建的套接字), 接收消息时需要使用重叠IO结构(overlapped I/O),除非lpOverlapped与lpCompletionRoutine参数都是NULL。这时,这个套接字将被视为非重叠套接字。当所有的缓存区都被接收完成了,将会执行一个动作来表示操作完成,这个动作可能是调用lpCompletionRoutine参数指定的完成例程或者是引发一个event对象。如果操作没有立即完成, 最终的完成状态通过完成例程或者 WSAGetOverlappedResult得到。

对于非重叠套接字来说,最后两个参数lpOverlapped与lpCompletionRoutine被忽略(设置为NULL)时WSARecv 与 recv的功能相同。接收到的数据从接收缓冲区中(应该是指系统的套接字堆栈)拷贝到用户缓冲区,如果当前没有收到数据或没有任何数据传输,套接字将被阻塞直至数据接收完毕后才返回。

dwFlags参数使用的标志与含义如下:
值        含义
MSG_DONTROUTE        指定的数据不应受制于路由。
MSG_OOB        接收带外数据,仅适用流套接字(SOCK_STREAM)
MSG_PARTIAL        指定lpBuffers只包含部分的信息。注意,返回的错误代码WSAEOPNOTSUPP将不支持部分消息传输的传输。

返回值:

错误代码:
WSANOTINITIALISED:在调用本API之前应成功调用WSAStartup()
WSAENETDOWN:网络子系统失效
WSAENOTCONN:套接字未连接。
WSAEINTR:通过WSACancelBlockingCall()函数取消(阻塞)调用
WSAEINPROGRESS:一个阻塞的Windows Sockets操作正在进行
WSAENETRESET:由于远端的复位造成连接的中止
WSAENOTSOCK:s参数不是一个有效的套接字
WSAEFAULT:lpBuffers 参数出错
WSAEOPNOTSUPP:设置了MSG_OOB,但是该套接字不是流式诸如SOCK_STREAM流类型的,                与套接字相关的通讯域不支持带外数据,或者套接字是单向的,只支持发送操作。
WSAESHUTDOWN:套接字已经关闭;一个套接字以SD_RECEIVE或 SD_BOTH的how参数                shutdown()后,无法进行WSARecv()调用。
WSAEWOULDBLOCK:重叠套接字:太多重叠的输入/输出请求。非重叠套接字:套                接口被标志为非阻塞,但是操作不能立即完成。
WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。
WSAEINVAL:套接字未用bind()捆绑,或者套接字未用重叠标志创建
WSAECONNABORTED:由于超时或其他原因引起虚电路的中断
WSAECONNRESET:虚电路被远端复位。
WSAEDISCON:远端优雅的结束了连接。
WSA_IO_PENDING:成功启动一个重叠操作,过后将有完成指示。
WSA_OPERATION_ABORTED:由于套接字的关闭,该重叠操作已被取消。
2016-10-9 20:56
0
雪    币: 44
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
上面两函数就是Windwos下套接字异发送与接收的主要函数
2016-10-9 21:04
0
雪    币: 145
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
不错, HPSocket确实好用 .
2016-10-31 15:45
0
游客
登录 | 注册 方可回帖
返回
//