gpt4 book ai didi

c - 使用 C 语言的套接字编程,使用 select() 函数

转载 作者:行者123 更新时间:2023-12-02 08:58:06 25 4
gpt4 key购买 nike

基于我从 this thread 得到的答案,我创建了这个:

    //Server 

sock_init(); //from SFL, see http://legacy.imatix.com/html/sfl/

timeout = 50000;

serv_sock_input[0] = TCP(1234);
serv_sock_input[1] = UDP(9876);

input_protocols[0] = "tcp";
input_protocols[1] = "udp";

while (1)
{
FD_ZERO(&sock_set);
for (x = 0; x<number_of_inputs; x++)
{
FD_SET(serv_sock_input[x], &sock_set);
}

select_timeout.tv_sec = timeout;
select_timeout.tv_usec = 0;

if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
printf("No requests");
else
{
for (x = 0; x<number_of_inputs; x++)
{
if (FD_ISSET(serv_sock_input[x],&sock_set))
{
printf("\nRequest on port %d: \n", x);
if ((strcmp(input_protocols[x],"tcp")) == 0) //in this case, 0 returned == TRUE
{
accept_socket(serv_sock_input[x]);
printf("Input TCP Port %d\n",x);
close_socket(serv_sock_input[x]);
}
else
{
printf("Input UDP Port %d\n",x);
}
}
}
}
}
sock_term();
}

int TCP (unsigned short port)
{
int sock;
struct sockaddr_in servAddr;

if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);

memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);

if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);

if (listen(sock, 5) < 0)
exit(1);

return sock;
}

int UDP (unsigned short port)
{
int sock; /* socket to create */
struct sockaddr_in servAddr; /* Local address */

/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
exit(1);

/* Construct local address structure */
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family */
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
servAddr.sin_port = htons(port); /* Local port */

/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);


return sock;
}

//Client
sock_init();

if ((client_sock_output = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);

memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(1234);

if (connect(client_sock_output, (struct sockaddr *) &client_addr, sizeof(client_addr)) < 0)
exit(1);

closesocket(client_sock_output);

sock_term();

当服务器启动时,服务器会在 if(select(...)) 语句处被阻塞。

因此,当我运行服务器,然后运行客户端时,客户端连接到服务器(有时在连接之前需要运行几次客户端)。然后 if(select...)) 语句不再为 true,而是继续执行 else。

之后,客户端关闭连接,程序结束。但是,这就是我的问题发生的地方,if(select(...)) 语句始终为 false。我得到这个输出:

Request on port 0:  
Input TCP Port 0

Request on port 1:
Input UDP Port 1

此输出将永远重复。为什么它不会卡在 if(select(...)) 处?

最佳答案

你有两个问题:你不明白accept()在TCP中是如何工作的,并且你需要读取UDP中传入的数据。

select() 告诉您监听套接字有要接受的连接,或者读套接字有要读取的数据。

要让 select 停止告诉您这一点,您需要实际读取数据或接受连接。

在你的UDP分支中,你需要调用receiv来实际获取数据。如果您不这样做,select 将不断告诉您您有数据。

在您的 TCP 分支中,您调用accept_socket。我不知道你的实现是什么,但关闭你刚刚调用accept()的套接字很可能是错误的。 Accept() 为您返回一个新的套接字 - 您应该用于 IO 的套接字。如果有什么需要关闭,那就是新的套接字。

关于c - 使用 C 语言的套接字编程,使用 select() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3372605/

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