为什么我的winsocks2有时会发送10057错误的结果?
我做了正常(?)步骤的tcp套接字连接,如下面的代码所示。但发送有时导致错误,而服务器端打印一些日志,说连接,我不知道我的代码有什么问题。任何帮助表示赞赏。 有关稳定和可靠的Windows套接字编程的任何信息,赞赏。为什么我的winsocks2有时会发送10057错误的结果?
MSDN描述约10057错误:
Socket is not connected.A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this error—for example, setsockopt setting SO_KEEPALIVE if the connection has been reset.
PS:在下面的代码段的真实IP地址是由127.0.0.1取代。代码不可运行。
int connect_to_server() {
SOCKET soc;
SOCKADDR_IN serveraddr;
SOCKADDR_IN clientaddr;
unsigned char buf[1024];
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
/* create a tcp socket; */
if ((soc = socket(AF_INET, SOCK_STREAM, 0/*IPPROTO_TCP*/)) <= 0)
{
LOGFMTF("errcode[-1], create socket fail!");
return -1;
}
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9102);
serveraddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
unsigned long mode = 1; // 1 to enable non-blocking socket
if (ioctlsocket(soc, FIONBIO, &mode) == SOCKET_ERROR) {
LOGFMTF("errcode[-2], ioctlsocket fail.");
return -2;
}
if (::connect(soc, (SOCKADDR *)&serveraddr, sizeof(serveraddr)) != 0)
{
/* FIONBIO socket enters here can go run; non-FIONBIO socket enters here stands for real error;*/
if (WSAGetLastError() != WSAEWOULDBLOCK) {
LOGFMTF("errcode[-3], connect fail.");
//return -3;
}
//return -1;
}
g_client_fd = soc;
LOGFMTT("client_fd[%d]", g_client_fd);
LOGFMTT("connect to server last err[%d].", WSAGetLastError());
return 0;
}
/** send loop; */
DWORD WINAPI send_thread_loop(LPVOID pM) {
LOGFMTT("send thread[%d] start.", GetCurrentThreadId());
for (;!g_to_exit;)
{
QMutexLocker locker(&g_send_queue_lock);
if (g_send_queue.count() == 0) {
Sleep(Send_Thread_Gap);
}else {
LOGFMTT("send one packet.");
int pakcet_size = g_send_queue.begin()->size;
char *addr = g_send_queue.begin()->data;
::send(g_client_fd, addr, pakcet_size, 0);
/* ------------!Attention begin------------ */
LOGFMTT("send last err[%d].", GetLastError());--------> sometimes got 10057 error.
/* ------------!Attention end------------ */
delete[]addr;
g_send_queue.erase(g_send_queue.begin());
}
}
LOGFMTT("send thread[%d] exit.", GetCurrentThreadId());
return 0;
}
int start_net_thread() {
g_recv_thread = CreateThread(NULL, 0, recv_thread_loop, NULL, 0, NULL);
g_send_thread = CreateThread(NULL, 0, send_thread_loop, NULL, 0, NULL);
return 0;
}
int main(){
if(connect_to_server() != 0)
{
QMessageBox msgBox;
msgBox.setText("failed.");
msgBox.exec();
return -1;
}
start_net_thread();
return 0;
}
希望我的浅浅的答案将有助于某人。
原来我的ioctlsocket
客户端套接字为非阻塞模式之前connect
。当connect
返回时,连接可能无法完成,但我立即启动发送线程。有机会发送线程send
数据到未连接的soeckt。
与MSDN一样,使用非阻塞套接字,连接尝试不能立即完成。
PS:send
可以发送小于预期字节经由send
第三个参数指定字节。
int remain_size = pakcet_size;
int this_read_cnt = 0;
for (;;) {
if ((this_read_cnt = ::send(g_client_fd, addr+ pakcet_size - remain_size, remain_size, 0)) != SOCKET_ERROR) {
remain_size = pakcet_size - this_read_cnt;
}
else {
LOGFMTT("send last err[%d].", GetLastError());
}
if (remain_size == 0) {
delete[]addr;
g_send_queue.erase(g_send_queue.begin());
break;
}
}
这不是'改进'。你让糟糕的代码变得更糟。 – EJP
Why did my winsocks2 send result in 10057 error sometimes?
它没有。至少,没有证据表明它确实如此。
::send(g_client_fd, addr, pakcet_size, 0);
/* ------------!Attention begin------------ */
LOGFMTT("send last err[%d].", GetLastError());--------> sometimes got 10057 error.
它是无效的调用WSAGetLastError()
除非有为一个错误,在这种情况下会被通过信号返回send()
-1。但是,由于你没有检查这个,除了你在send()
附近的编码差,没有证据表明这个问题有待解决。它应显示为:
if (::send(g_client_fd, addr, pakcet_size, 0) == -1)
{
/* ------------!Attention begin------------ */
LOGFMTT("send last err[%d].", GetLastError());--------> sometimes got 10057 error.
}
注意该单词拼写为“数据包”,而不是“pakcet”。
片状连接,连接丢失,忽略错误代码。 – CodeCaster
@CodeCaster也许我有很多功课要做。如果我忽略此错误并尝试稍后再发送,那么可以吗?我已经改变了我的代码以改进它,并且会测试更多以查看它是否适用于我的明天工作。 – waterd
@CodeCaster我想我错过了一些关于我的错误的重要背景。连接到服务器,发送线程开始和我的fisrt尝试发送登录数据包到服务器是逐行的。到现在为止,如果第一次发送失败,不会再发送数据包。所以我在第一个回复中有这个问题。更多的工作需要等到明天。谢谢您的回复。 – waterd