套接字:为什么accept() 挂起但connect() 成功?

Jea*_*ger 5 c++ sockets

我一直试图理解为什么在我的服务器上,当客户端成功调用 connect() 时,accept() 调用仍然阻塞?

服务器.cpp

#include <errno.h>
#include <strings.h>

#include <iostream>
#include "globals.h"

using namespace std;

/* Declaring errno */
extern int errno;

/* Function for printing error */

void report_error(char *s)
{
     printf("receiver: error in%s, errno = %d\n", s, errno);
     exit(1);
}

int main(int argc, char *argv[])
{
     int s,c;
     int res;
     struct sockaddr_in socket_address = {0}, client_sa = {0};
     unsigned int client_sa_len = sizeof(client_sa);


     /* Creating the socket and returns error if unsuccesfull */
     if((s= socket(AF_INET, SOCK_DGRAM, PF_UNSPEC)) == -1)
        report_error("socket");

     socket_address.sin_family = AF_INET;
     socket_address.sin_addr.s_addr=INADDR_ANY;
     socket_address.sin_port = htons(5318 + 2000);

    /* Binding the socket and returns error if unsuccesfull */
     if(bind(s, (struct sockaddr *)&socket_address, sizeof(socket_address))== -1)
        report_error("bind");

    listen(s, 10);
    cout << "listening on port\n";

    while(1)
    {

        /*The server just hangs here*/
        c = accept(s, (struct sockaddr*)&client_sa, &client_sa_len);
        if (c > 0)
        {
            cout << "LOG: Was the accept successful" << endl;
            res = fork();
            if (res < 0)
            {
                perror("Forking of child failed");
            }
        }

        if(res == 0)
        {
            //close(s);
            char msg[MSGL], reply[50], args[MSGL];
            char command[MSGL];
            cout << "LOG: Get message?" << endl;
            GetRequest(msg, c, &client_sa);
            if( (msg[0] == 'c')  && (msg[1] == 'd') && (msg[2] == ' '))
            {
                strncpy(command, "cd", sizeof(command));

                int arg_i = 0;
                for(int i = 3; msg[i] != '\n'; ++i)
                {
                    args[arg_i] = msg[i];
                    ++arg_i;
                }
            }
            else
            {
                for(int i = 0; msg[i] != '\n'; ++i)
                {
                    command[i] = msg[i];
                }
            }

        else
        {
            if(c > 0)
            {
                //close(c);
            }
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我运行此服务器时,它会打印它正在侦听,然后当我初始化客户端时,它不会说客户端已连接

客户端.cpp

#include <errno.h>
#include <arpa/inet.h>

#include <iostream>
#include <string>
#include "globals.h"

using namespace std;


/* Declaring errno */
extern int errno;

int main(int argc, char *argv[])
{
     int s;
     char* server_address = argv[1];
     char command[MSGL];
     char reply[MSGL];
     int connect_success;
     struct sockaddr_in sa = {0} ,cli_sa = {0};
     int length = sizeof(sa);
     struct hostent *hp;

        cli_sa.sin_family = AF_INET;
        cli_sa.sin_addr.s_addr=INADDR_ANY;
        cli_sa.sin_port = htons(5318 + 2001);
     /* FILL SOCKET ADDRESS*/
        if((hp = gethostbyname(server_address))==NULL)
            report_error("gethostbyname");


        bcopy((char*)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);

        sa.sin_family = hp->h_addrtype;

        //memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
        sa.sin_port = htons(5318 + 2000); /* define port number based on student ID*/

     /* Creating the socket and returns error if unsuccessfull */
     if((s=socket(AF_INET, SOCK_DGRAM, PF_UNSPEC))== -1)
        report_error("socket");

    /* Binding the socket and returns error if unsuccesfull */
     if(bind(s, (struct sockaddr *)&cli_sa, sizeof(cli_sa))== -1)
        report_error("bind");

    connect_success = connect(s,(struct sockaddr*) &sa, length);
    cout << connect_success << endl;
    if (connect_success < 0)
    {
        report_error("connect");
        cout << "LOG: is there an error?" << endl;
    }
    cout << "LOG: is the connection made?" << endl;
    while(1)
    {
        cout << "myRPC>>";
        fgets(command,MSGL,stdin);
        if (DoOperation(command,reply,s,sa) == SEND_FAILURE)
        {
            cout << "Error: sending command\n";
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Sam*_*hik 2

我相当确定您的服务器进程有未定义的行为。

accept()用于connect()TCP 套接字。您正在创建 UDP 套接字。对于 UDP 套接字,所做的只是connect()设置 的默认地址send(),并且它总是立即成功。这在 的手册页中connect(2)有解释,您一定应该阅读:

如果套接字sockfd是SOCK_DGRAM类型,则addr是默认发送数据报的地址,也是接收数据报的唯一地址。

我预计accept()UDP () 套接字会失败SOCK_DGRAM,很可能是EINVAL. 如果您检查服务器代码中的逻辑,当accept()失败时,res在语句中测试其值之前永远不会被初始化if()

未定义的行为。