C套接字编程:connect()挂起

时间:2010-04-16 11:50:17

标签: c connection client-server

嘿所有,我准备撕掉我的头发了。我有这个尝试连接到服务器的客户端,一切似乎都很好,使用gethostbyname()socket()bind(),但在尝试connect()时,它只是挂在那里并且服务器没有从客户端看到任何内容。我知道服务器可以工作,因为另一个客户端(也在C中)可以很好地连接。是什么原因导致服务器看不到此传入连接?我在这里结束了我的智慧。两个不同的客户也非常相似,所以我更加迷失。

    if (argc == 2)  {
    host = argv[1];         // server address
}
else    {
    printf("plz read the manual\n");
    exit(1);
}

hserver = gethostbyname(host);
if (hserver)    {
    printf("host found: %p\n", hserver);
    printf("host found: %s\n", hserver->h_name );
}
else    {
    printf("host not found\n");
    exit(1);
}

bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(hserver->h_addr);
server_address.sin_port = htons(SERVER_PORT);

bzero((char * ) &client_address, sizeof(client_address)); // copy zeroes into string
client_address.sin_family = AF_INET;
client_address.sin_addr.s_addr = htonl(INADDR_ANY);
client_address.sin_port = htons(SERVER_PORT);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
    exit(1);
else    {
    printf("socket is opened: %i \n", sockfd);
    info.sock_fd = sockfd;
    rv = fcntl(sockfd, F_SETFL, O_NONBLOCK); // socket set to NONBLOCK
    if(rv < 0)
        printf("nonblock failed: %i %s\n", errno, strerror(errno));
    else
        printf("socket is set nonblock\n");
}

timeout.tv_sec = 0;     // seconds
timeout.tv_usec = 500000; // micro seconds ( 0.5 seconds)
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));

rv = bind(sockfd, (struct sockaddr *) &client_address, sizeof(client_address));
if (rv < 0)     {
    printf("MAIN: ERROR bind() %i: %s\n", errno, strerror(errno));
    exit(1);
}
else
    printf("socket is bound\n");

rv = connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
printf("rv = %i\n", rv);
if (rv < 0)     {
    printf("MAIN: ERROR connect() %i:  %s\n", errno, strerror(errno));
    exit(1);
}
else
    printf("connected\n");

非常感谢任何想法或见解。

-Fourier

编辑: 如果未在非块上设置套接字,则它会挂起。 如果套接字设置为非阻塞,那么我得到ERROR connect() 115: Operation now in progress

[EINPROGRESS]     O_NONBLOCK设置为套接字的文件描述符,无法立即建立连接;连接应以异步方式建立。

我还想提一下,服务器和客户端在彼此相邻的计算机上运行,​​由一个路由器连接。

4 个答案:

答案 0 :(得分:3)

gethostbyname()函数以网络字节顺序生成地址,因此您无需通过htonl()传递它们。此外,hostent->h_addr条目是指向地址的指针。替换此行:

server_address.sin_addr.s_addr = htonl(hserver->h_addr);

使用:

memcpy(&server_address.sin_addr, hserver->h_addr, hserver->h_length);

答案 1 :(得分:1)

我看到你将套接字设置为O_NONBLOCK模式。

因此,连接必须返回-1并根据the man page of connecterrno设置为EAGAIN。

然后,您可以使用套接字上的select()知道连接何时成功。

这是控制连接超时的一种非常常见的模式(因为select()必须以超时方式提供)。

答案 2 :(得分:0)

检查是否可以连接程序telnet(它接受服务器名称和端口号)。如果可行,则错误必须在您的代码中。如果telnet也挂起,请检查防火墙设置。

答案 3 :(得分:0)

如果您想从同一台机器连接两次,我可以看到问题的原因。

您绑定了clientsocket。您的代码非常具体地将客户端套接字绑定到固定端口(服务器端口)。这使得O / S不会在选择用于建立连接FROM的可用端口时自由。如果一个进程已分配端口(它已成功绑定()和连接()到服务器),则另一个进程不能使用相同的端口。

如果没有令人信服的理由从特定端口发送流量,请让O / S通过更改此行找到可用端口

client_address.sin_port = htons(SERVER_PORT);

client_address.sin_port = 0;