gpt4 book ai didi

C套接字编程: select() is returning 0 despite messages sent from server

转载 作者:可可西里 更新时间:2023-11-01 02:40:23 24 4
gpt4 key购买 nike

我正在使用 select() 从服务器接收 recv() 消息,使用 TCP/IP。当我 send() 来自服务器的消息时,它返回合理数量的字节,表示发送成功。当我使用 while 循环到 recv() 时,它确实成功到达了客户端。一切都很好,花花公子。

while(1)
recv() // obviously pseudocode

但是,当我尝试使用 select() 时,select() 从超时(设置为 1 秒)返回 0 并且在我的一生中无法弄清楚为什么它看不到从服务器发送的消息。我还应该提到,当服务器断开连接时,select() 也看不到,就像我要使用 recv() 一样,它会返回 0 到表示使用套接字的连接已经关闭。非常感谢任何意见或想法。

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>


#define SERVER_PORT 10000
#define MAX_CONNECTION 20
#define MAX_MSG 50


struct client
{
char c_name[MAX_MSG];
char g_name[MAX_MSG];

int csock;
int host; // 0 = not host of a multicast group

struct sockaddr_in client_address;

struct client * next_host;
struct client * next_client;
};

struct fd_info
{
char c_name[MAX_MSG];

int socks_inuse[MAX_CONNECTION];
int sock_fd, max_fd;
int exit;

struct client * c_sys;
struct sockaddr_in c_address[MAX_CONNECTION];

struct sockaddr_in server_address;
struct sockaddr_in client_address;

fd_set read_set;
};

struct message
{
char c_name[MAX_MSG];
char g_name[MAX_MSG];
char _command[3][MAX_MSG];
char _payload[MAX_MSG];

struct sockaddr_in client_address;
struct client peer;
};

int main(int argc, char * argv[])
{
char * host;
char * temp;

int i, sockfd;
int msg_len, rv, ready;
int connection, management, socketread;
int sockfds[MAX_CONNECTION];


// for three threads that handle new connections, user inputs and select() for sockets
pthread_t connection_handler, manager, socket_reader;

struct sockaddr_in server_address, client_address;
struct hostent * hserver, cserver;
struct timeval timeout;
struct message msg;
struct fd_info info;
info.exit = 0; // exit information: if exit = 1, threads quit
info.c_sys = NULL;

// looking up from the host database
if (argc == 3)
{
host = argv[1]; // server address
strncpy(info.c_name, argv[2], strlen(argv[2])); // client name
}
else
{
printf("plz read the manual, kthxbai\n");
exit(1);
}

printf("host is %s and hp is %p\n", host, hserver);
hserver = gethostbyname(host);
if (hserver)
{
printf("host found: %s\n", hserver->h_name );
}
else
{
printf("host not found\n");
exit(1);
}
// setting up address and port structure information on serverside
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
memcpy(&server_address.sin_addr, hserver->h_addr, hserver->h_length);
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);

// opening up socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
exit(1);
else
{
printf("socket is opened: %i \n", sockfd);
info.sock_fd = sockfd;
}

// sets up time out option for the bound socket
timeout.tv_sec = 1; // seconds
timeout.tv_usec = 0; // micro seconds ( 0.5 seconds)
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));

// binding socket to a port
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");

printf("MAIN: %li \n", client_address.sin_addr.s_addr);


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

fd_set readset;
FD_ZERO(&readset);
FD_ZERO(&info.read_set);
FD_SET(info.sock_fd, &info.read_set);

while(1)
{
readset = info.read_set;
printf("MAIN: %i \n", readset);
ready = select((info.max_fd)+1, &readset, NULL, NULL, &timeout);

if(ready == -1)
{
sleep(2);
printf("TEST: MAIN: ready = -1. %s \n", strerror(errno));
}
else if (ready == 0)
{
sleep(2);
printf("TEST: MAIN: ready = 0. %s \n", strerror(errno));
}
else if (ready > 0)
{
printf("TEST: MAIN: ready = %i. %s at socket %i \n", ready, strerror(errno), i);
for(i = 0; i < ((info.max_fd)+1); i++)
{
if(FD_ISSET(i, &readset))
{
rv = recv(sockfd, &msg, 500, 0);
if(rv < 0)
continue;
else if(rv > 0)
printf("MAIN: TEST: %s %s \n", msg._command[0], msg._payload);
else if (rv == 0)
{
sleep(3);
printf("MAIN: TEST: SOCKET CLOSEDDDDDD \n");
}

FD_CLR(i, &readset);
}
}

}
info.read_set = readset;

}

// close connection
close(sockfd);
printf("socket closed. BYE! \n");
return(0);

}

最佳答案

如果发生超时,那么您的readset 将最终没有设置文件描述符。然后用这个空集替换 info.read_set:

info.read_set = readset;

..所以你总是检查一个空的文件描述符集,这意味着你每次都会超时。

(顺便说一句,你真的不应该像那样分配文件描述符集 - 不能保证它们不包含需要深度复制的结构。可移植的方法是构建文件描述符每次都从头开始设置。)

关于C套接字编程: select() is returning 0 despite messages sent from server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2894008/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com