C# 套接字同时发送/接收

C# 套接字同时发送/接收,c#,C#,有谁能指出你不能同时在插座上发送和接收的原因吗 据我所知,有两条溪流,一条推一条拉 如果您尝试同时发送/接收,则会出现wasealready错误 套接字抛出wasealready错误(10035)的原因是什么 它是否与接收方发送回的ack窗口有关? 好像要让窗口的线路保持打开状态?首先,我认为您对错误代码感到困惑。以下是一些可能相关的代码: WSAEREADY(10037)-您试图发出一个已经在进行中的请求。例如,尝试用已经在连接中的一个套接字来编写代码>连接()/ .< WSAEINPROG

有谁能指出你不能同时在插座上发送和接收的原因吗

据我所知,有两条溪流,一条推一条拉

如果您尝试同时发送/接收,则会出现wasealready错误

套接字抛出wasealready错误(10035)的原因是什么 它是否与接收方发送回的ack窗口有关?
好像要让窗口的线路保持打开状态?

首先,我认为您对错误代码感到困惑。以下是一些可能相关的代码:

  • WSAEREADY(10037)-您试图发出一个已经在进行中的请求。例如,尝试用已经在连接中的一个套接字来编写代码>连接()/<代码> .<
  • WSAEINPROGRESS(10036)-您试图一次发出多个阻塞操作,甚至跨多个线程
  • WSAEWOULDBLOCK(10035)-当套接字处于非阻塞模式时,您试图进行一个本应阻塞的呼叫(例如,在没有可用数据时recv)
阻止您同时执行两个阻塞操作的主要因素是
WSAEINPROGRESS
错误-Winsock 1.1 API中的限制只允许您一次执行一个阻塞操作。您可以通过使用非阻塞重叠调用和Winsock 2.0 API来模拟阻塞调用来解决这个问题。例如:

SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
WSAEVENT hEvent = WSACreateEvent();
WSAEventSelect(sock, hEvent, FD_CONNECT); // register for connect notification
long iMode=1;
ioctlsocket(sock,FIONBIO,&iMode); // set non-blocking mode

WSAConnect(sock, address, sizeof(address), NULL, NULL, NULL, NULL);
WSAWaitForMultipleEvents(1, &events, FALSE, INFINITE, FALSE);

WSANETWORKEVENTS connect_result;
WSAEnumNetworkEvents(sock, hEvent, &connect_result);
if (connect_result.iErrorCode[FD_CONNECT] != 0) {
  // connect failed, do something about it
}
WSACloseEvent(hEvent);

iMode = 0;
ioctlsocket(sock,FIONBIO,&iMode); // clear non-blocking mode; it won't play well with overlapped IO below

// Start an overlapped send
char *my_data = "Hello, world!";
WSAOVERLAPPED send_overlapped;
WSABUF send_buf;
send_buf.len = strlen(my_data);
send_buf.buf = my_data;
send_overlapped.hEvent = WSACreateEvent();
DWORD bytesSent;
WSASend(sock, &send_buf, 1, &bytesSent, 0, &send_overlapped, NULL);
if (WSAGetLastError() != WSA_IO_PENDING) {
    // something went wrong, handle the error...
}


// Start an overlapped receive
char rdata[256];
WSAOVERLAPPED recv_overlapped;
WSABUF recv_buf;
recv_buf.len = sizeof(rdata);
recv_buf.buf = rdata;
recv_overlapped.hEvent = WSACreateEvent();
DWORD bytesRecvd;
WSARecv(sock, &recv_buf, 1, &bytesRecvd, NULL, &recv_overlapped, NULL);
if (WSAGetLastError() != WSA_IO_PENDING) {
    // something went wrong, handle the error...
}

// Now wait for both to finish
WSAEVENT events[2];
events[0] = recv_buf.hEvent;
events[1] = send_buf.hEvent;
WSAWaitForMultipleEvents(2, events, TRUE, INFINITE, TRUE);
这种方法有点复杂,但非常灵活——一旦启动了重叠的I/O作业,同一个线程就可以继续执行其他工作(只要保留缓冲区和未分配的内容!)。需要注意的一点是,如果在GUI线程上执行此操作,则需要更改消息循环-为了完成重叠事件,发出重叠事件的线程需要使用eg
MsgWaitForMultipleEvents
执行可警报的等待。在上面的示例中,我使用
WSAWaitForMultipleEvents
执行此警报等待。此外,发出重叠I/O请求的线程在请求完成之前不得终止


有关重叠I/O的更多一般信息,请参阅此MSDN页面:

10035是WSAEWOULDBLOCK,您是否已将套接字置于非阻塞模式?