C ++ Winsock服务器接受函数返回10022错误

时间:2019-06-05 18:09:36

标签: c++ codeblocks winsock

我摆脱了错误,现在我似乎还停留在其他东西上。

我在Code :: Blocks上有单独的Winsock客户端和服务器程序。我正在尝试从客户端向服务器发送消息,但是服务器程序似乎在accept()函数之前冻结了,除了“侦听传入的连接”之外什么也没做。输出。客户端缓冲区中的消息永远不会显示在服务器控制台中。

服务器程序中的accept函数肯定看起来有问题。这似乎是服务器程序冻结的地方。我尝试在那之后键入随机的提示行,但没有输出。

在“消息已发送”之后,客户端似乎也冻结了。但是几分钟后,我收到“ recv failed”,然后收到“ Reply Received”,然后出现一系列表情符号。我想我下面有链接的图片。

enter image description here

这是我的客户代码:

#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{

    WSADATA wsaData;
    SOCKET sock;
    sockaddr_in server;
    char *buffer, server_reply[2000];
    int recv_size;

    int iResult;

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed: %d\n", iResult);
} else {
     printf("WSAStartup successful!: %d\n", iResult);
}

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET){
    printf("Socket not created.\n");
} else {
    printf("Socket created.\n");
}

    server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(80);

    if(connect(sock, (SOCKADDR *)&server, sizeof(server)) != 0){
        printf("Connect Error : %d" , WSAGetLastError());
    } else {
        printf("Connected\n");
    };

    buffer = "Hello there!";
    send(sock, buffer, sizeof(buffer), 0);

        printf("Message Sent.\n");


    if((recv_size = recv(sock , server_reply , 2000 , 0)) == SOCKET_ERROR)
    {
        puts("recv failed");
    }

    puts("Reply received\n");
    //Add a NULL terminating character to make it a proper string before printing
    server_reply[recv_size] = '\0';
    puts(server_reply);


    closesocket(sock);
    WSACleanup();

    return 0;
}

这是我的服务器代码:

#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{

    WSADATA wsaData;
    SOCKET server1, client;
    sockaddr_in serverAddr, clientAddr;


    int iResult;

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed: %d\n", iResult);
} else {
     printf("WSAStartup successful!: %d\n", iResult);
}

server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
    printf("Socket not created.\n");
} else {
    printf("Socket created.\n");
}

    serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8888);

    if(bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR){
        printf("Bind failed. : %d" , WSAGetLastError());
    } else {
        printf("Bind successful.\n");
    }

    if(listen(server1, SOMAXCONN) != 0){
        printf("Server not listening. : %d" , WSAGetLastError());
    } else {
        cout << "Listening for incoming connections..." << endl;
    }



    char buffer[1024];
    int clientAddrSize = sizeof(clientAddr);
    if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
    {
        printf("Connect Error : %d" , WSAGetLastError());
    } else {
        cout << "Client connected!" << endl;
        recv(client, buffer, sizeof(buffer), 0);
        cout << "Client says: " << buffer << endl;
        memset(buffer, 0, sizeof(buffer));

        closesocket(client);
        closesocket(server1);
        cout << "Client disconnected." << endl;
    }
    WSACleanup();

    return 0;
}

我正在尝试使用CodeBlocks中的C ++构建与我的客户端程序一起使用的Winsock服务器程序。但是,accept函数返回错误代码10022,根据我的理解,该错误代码表示参数无效。我看不到accept函数中的任何参数都无效。感谢您的帮助!

int main()
{

    WSADATA wsaData;
    SOCKET server1, client;
    sockaddr_in serverAddr, clientAddr;


    int iResult;

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed: %d\n", iResult);
} else {
     printf("WSAStartup successful!: %d\n", iResult);
}

server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
    printf("Socket not created.\n");
} else {
    printf("Socket created.\n");
}

    serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8888);

    bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
    listen(server1, SOMAXCONN);

    cout << "Listening for incoming connections..." << endl;

    char *buffer;
    int clientAddrSize = sizeof(clientAddr);
    if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
    {
        printf("Connect Error : %d" , WSAGetLastError());
    } else {
        cout << "Client connected!" << endl;
        recv(client, buffer, sizeof(buffer), 0);
        cout << "Client says: " << buffer << endl;
        memset(buffer, 0, sizeof(buffer));

        closesocket(client);
        closesocket(server1);
        cout << "Client disconnected." << endl;
    }
    WSACleanup();

    return 0;
}

2 个答案:

答案 0 :(得分:2)

10022为WSAEINVAL。根据{{​​3}}文档:

  

WSAEINVAL
  listen函数未在accept之前调用。

accept()文档还说:

  

WSAEINVAL
  10022

     

无效的参数。

     

提供了一些无效的参数(例如,为setsockopt函数指定了无效的级别)。在某些情况下,它还引用套接字的当前状态,例如在未监听的套接字上调用accept

好的,让我们来看一下您的listen()通话:

listen(server1, SOMAXCONN);

假设server1是一个有效的套接字(您可以检查一下,但是如果socket()失败则不停止程序),这没什么异常。

您没有检查任何listen()错误。根据{{​​3}}文档,可能的错误之一是:

  

WSAEINVAL
  套接字尚未与bind绑定。

好的,接下来让我们看看您的bind()通话:

bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));

同样,您没有检查任何bind()错误。根据{{​​3}}文档,可能的错误之一是:

  

WSAEADDRNOTAVAIL
  请求的地址在其上下文中无效。

     

如果name参数所指向的指定地址不是此计算机上的有效本地IP地址,则会返回此错误。

您可能会得到,因为您没有正确地填充serverAddr,特别是在此行上

serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);

INADDR_ANY被定义为0,因此您将S_addr字段设置为inet_addr(0)的结果,该结果无效,因此INADDR_NONE(0xFFFFFFFF )返回,这也是您无需检查的内容。正确的分配方法是按原样使用INADDR_ANY

serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;

因此,总结起来,您的错误处理是不充分的,允许错误累积,直到您最终决定完全对accept()进行错误处理为止,为时已晚。您需要一路检查每个函数的结果是否失败,遇到错误时请停止。

答案 1 :(得分:1)

glimpse()采用inet_addr,它以数字和点表示法表示IPv4地址。您正在将const char*传递给此函数,它可以编译但无法正常工作,因为INADDR_ANY等于0,因此使用空指针调用INADDR_ANY。您应该检查该函数的返回码,-1表示错误。我想你明白了。

如果您想绑定任何本地地址,则应将inet_addrINADDR_ANY结合使用:

htonl

serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

导致不确定的行为。缓冲区未初始化。对此char *buffer; recv(client, buffer, sizeof(buffer), 0); 的调用要读取4/8字节-recv,并写入未初始化的 buffer 指针。您需要创建一些初始大小的缓冲区,例如通过调用malloc / calloc:

sizeof(buffer)