WSASend()的操作

我想请教下,WSASend()的操作
最新回答
敷衍丶换来无言的结局ゝ

2024-09-17 02:41:25

Overlapped Socket I/O
如果重叠操作立即完成,WSASend返回0 同时设置lpNumberOfBytesSent指向的变量为发送的字节数。如果重叠操作成功初始化将稍后完成,WSASend返回 SOCKET_ERROR同时设置错误码为WSA_IO_PENDING. 这时,lpNumberOfBytesSent指向的变量不会被更新。当重叠IO完成以后,发送的数量可以用两种方式取得:如果指定了完成例程(即lpCompletionRoutine),那么通过完成例程的cbTransferred参数得到。也可以调用WSAGetOverlappedResult,通过lpcbTransfer得到。
Note如果一个线程退出了,那么它发出的IO操作都将取消。对于重叠sockets来说, 如果在操作完成之前,线程被关闭了,未决的异步操作可能会失败,更详细的信息, 参见ExitThread。
WSASend可以在下列函数的完成例程中调用:WSARecv,WSARecvFrom,WSASend, orWSASendTo. 这可以让时间敏感的数据传送得到更高的

优先级
(似乎也就是说你如果想让数据发得快一点,它就给你个机会快一点)。
在重叠操作期间,lpOverlapped指向的数据必须一直是合法的(你别弄些局部变量放进去:-) )。如果同时有多个未决的IO操作,每一个操作必须有单独的WSAOVERLAPPED结构。
如果lpCompletionRoutine为空, 当操作完成时,如果lpOverlapped里面的hEvent是一个合法的event对象,系统会设置这个event为有信号(signaled )。用户的
应用程序
可以用WSAWaitForMultipleEventsorWSAGetOverlappedResult来等待这个事件。
如果lpCompletionRoutine非空,hEvent被忽略,它可以被用于传送上下文信息给完成例程。如果调用方设置了一个非空的lpCompletionRoutine随后又在同样的重叠IO上调用WSAGetOverlappedResult又没有设置WSAGetOverlappedResult 的参数为TRUE. 这时hEvent是未定义的,同时等待hEvent也将产生不预知的结果。(就是说你不要同时用完成例程和WSAGetOverlappedResult或者hevnet)。
这里的完成例程和windows文件IO的完成例程一样。一直到有线程处于alertable wait state状态时,完成例程才会被调用,例如调用WSAWaitForMultipleEvents并设置fAlertable为TRUE。
数据传送层(transport providers )允许用户在重叠socket的完成例程里发出send和receive调用,同时保证对于一个给定的socket,IO的完成例程不会嵌套。这可以让时间敏感的数据传送得到更高的优先级。
下面的代码是完成例程的原型:
The following C++ code example is a prototype of the completion routine.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
完成例程不过是用户定义的一个函数的
占位符
而已。(就是说它是个
回调函数
)dwError说明重叠IO完成的状态,这个重叠IO由lpOverlapped指定。cbTransferred是发送的字节数。当前没有使用dwFlags,他总是被设为0。该函数没有
返回值

Returning from this function allows invocation of another pending completion routine for this socket. All waiting completion routines are called before the alertable thread's wait is satisfied with a return code of WSA_IO_COMPLETION. 完成例程可能以任何次序被调用,不必是重叠IO完成的次序。但是提交发送的多个缓冲区会确保按照指定的次序发送。
如果你使用完成端口,要注意调用WSASend的次序就是就是缓冲区被填充的次序。不要从不同的线程中同时调用同一个socket上的WSASend函数,因为可能导致缓冲区中的数据处于不可预知的次序。
Example Code
下面的代码演示如何以重叠IO的方式使用WSASend函数。
#include <winsock2.h>
#include <ws2tcpip.h>
#include <
stdio.h
>
#include <
stdlib.h
>
#define DATA_BUFSIZE 4096
#define SEND_COUNT 10
void __cdecl main()
{
WSADATA wsd;
struct addrinfo *result = NULL,
hints = ;
WSAOVERLAPPED SendOverlapped = ;
SOCKET ListenSocket = INVALID_SOCKET,
AcceptSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD SendBytes, Flags;
char buffer[DATA_BUFSIZE];
int err, rc, i;
// Load Winsock
rc = WSAStartup(MAKEWORD(2,2), &wsd);
if (rc != 0) {
fprintf(stderr, Unable to load Winsock: %d\n, rc);
return;
}
// Initialize the hints to obtain the
// wildcard bind address for IPv4
hintsai_family = AF_INET;
hintsai_socktype = SOCK_STREAM;
hintsai_protocol = IPPROTO_TCP;
hintai_flags = AI_PASSIVE;
rc =getaddrinfo(NULL, 27015, &hints, &result);
if (rc != 0) {
fprintf(stderr, getaddrinfo failed: %d\n, rc );
return;
}
ListenSocket = socket(result->ai_family,
result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
fprintf(stderr, socket failed: %d\n,
WSAGetLastError());
freeaddrinfo(result);
return;
}
rc = bind(ListenSocket, result->ai_addr,
(int)result->ai_addrlen);
if (rc == SOCKET_ERROR) {
fprintf(stderr, bind failed: %d\n,
WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return;
}
rc = listen(ListenSocket, 1);
if (rc == SOCKET_ERROR) {
fprintf(stderr, listen failed: %d\n,
WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return;
}
// Accept an incomingconnection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
fprintf(stderr, accept failed: %d\n,
WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return;
}
printf(Client Accepted...\n);
// Create an event handle and setup an overlapped structure.
SendOverlapped.hEvent =WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
fprintf(stderr, WSACreateEvent failed: %d\n,
WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
closesocket(AcceptSocket);
return;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for(i=0; i < SEND_COUNT ;i++) {
rc = WSASend(AcceptSocket, &DataBuf, 1,
&SendBytes, 0, &SendOverlapped, NULL);
if ( (rc == SOCKET_ERROR) &&
(WSA_IO_PENDING != (err = WSAGetLastError()))) {
fprintf(stderr, WSASend failed: %d\n, err);
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
fprintf(stderr, WSAWaitForMultipleEvents failed: %d\n, WSAGetLastError());
break;
}
rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &SendBytes, FALSE, &Flags);
if (rc == FALSE) {
fprintf(stderr, WSASend operation failed: %d\n, WSAGetLastError());
break;
}
printf(Wrote %d bytes\n, SendBytes);
WSAResetEvent(SendOverlapped.hEvent);
}
WSACloseEvent(SendOverlapped.hEvent);
closesocket(AcceptSocket);
closesocket(ListenSocket);
freeaddrinfo(result);
WSACleanup();
return;
}