插座:为什么Accept()挂起,但是Connect()成功

Sockets: Why is accept() hanging but connect() is succeeding?

本文关键字:但是 Connect 成功 挂起 Accept 插座 为什么      更新时间:2023-10-16

我一直在尝试了解为什么在我的服务器上accept()调用客户端时仍在阻止connect()呼叫?

server.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 = %dn", 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 portn";
    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;
}

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

client.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 commandn";
        }
    }
    return 0;
}

我可以肯定您的服务器流程具有不确定的行为。

accept()connect()适用于TCP插座。您正在创建UDP插座。对于UDP插座,connect()所做的所有操作都是为send()设置默认地址,并且它始终立即成功。这在connect(2)的手册页面中进行了解释,您绝对应该阅读:

如果套接字sockfd是类型sock_dgram,则addr是地址 默认向哪些数据报到了哪些数据报,也是唯一的地址 收到了哪些数据报。

我希望accept()为UDP(SOCK_DGRAM)插座失败,最有可能使用EINVAL。如果您在服务器代码中查看逻辑时,当accept()失败时,resif()语句中测试其值之前就永远不会初始化。

未定义的行为。

相关文章: