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

时间:2016-12-01 04:13:18

标签: c++ sockets

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

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

当我运行此服务器时,它会打印出正在侦听的内容,然后当我初始化客户端时,它并不表示客户端已连接

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 command\n";
        }
    }

    return 0;
}

1 个答案:

答案 0 :(得分:1)

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

connect()send()用于TCP套接字。您正在创建UDP套接字。对于UDP套接字,accept()所做的全部设置为SOCK_DGRAM的默认地址,并且它总是立即成功。这是in the manual page for connect(2)的解释,您一定要阅读:

  

如果套接字sockfd的类型为SOCK_DGRAM,则addr是地址   默认情况下向哪些数据报发送,以及唯一的地址   收到哪些数据报。

我希望EINVAL对于UDP(accept())套接字失败,很可能是res。如果您查看服务器代码中的逻辑,当if()失败时,json_encode()永远不会在<?php // ASSUMING YOU PERFORMED SOME DATABASE TRANSACTIONS AND FINALLY // YOUR RESULT-SET (CONSISTING OF AN ARRAY OF ROWS) LOOKS LIKE THIS: $resultSet = $pdoStatement->fetchAll(PDO::FETCH_ASSOC); // YOU MIGHT PROCESS THE RESULT FURTHER THROUGH A LOOP OR WHATEVER // HOWEVER, ONCE YOU ARE DONE PROCESSING, YOU MAY NOW GENERATE THE JSON DATA $jsonData = json_encode($resultSet); 语句中测试其值之前进行初始化。

未定义的行为。