为什么我的winsocks2有时发送10057错误?

时间:2017-09-27 14:05:39

标签: c++ windows sockets tcp winsock2

我使用正常(?)步骤进行tcp套接字连接,如下面的代码所示。但是发送有时会导致 10057 错误,而服务器端会打印一些说明连接的日志,我不知道我的代码有什么问题。任何帮助表示赞赏。  有关稳定和强大的Windows套接字编程的任何信息都很受欢迎。

关于10057错误的MSDN描述:

  

套接字未连接。由于套接字未连接而且(使用sendto在数据报套接字上发送时)未提供发送或接收数据的请求,因此未提供地址。任何其他类型的操作也可能返回此错误 - 例如,如果连接已重置,则setsockopt设置SO_KEEPALIVE。

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;
}

2 个答案:

答案 0 :(得分:2)

  

为什么我的winsocks2有时会导致10057错误?

没有。至少,没有证据表明它确实如此。

::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.
}

注意:这个单词拼写为'packet',而不是'pakcet'。

答案 1 :(得分:-1)

希望我的浅薄回答可以帮助别人。

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;
    }
}