gpt4 book ai didi

c - 监听()和选择()

转载 作者:行者123 更新时间:2023-11-30 14:57:35 31 4
gpt4 key购买 nike

我实际上在客户端-客户端应用程序方面遇到了麻烦。这个问题中的一切都与Unix网络编程环境有关。

这是我的情况:

  • 我有一个客户端(从现在起称为 C1),它调用 listen()在套接字上。
  • C1 输入 listenfd与之前的listen()关联的套接字调用适当的电话fd_set变量并调用 select()就在上面。
  • 一旦它收到来自另一个客户端的新传入连接(从现在开始称为 C2), select() procs,已成功创建连接 accept()和客户C1-C2开始沟通。
  • 我们调用 accept()返回 int accfdconnect()返回 int connfd .
  • 完成后,两者都会C1-C2使用 close(connfd) 关闭相关套接字, close (accfd) .

一旦完成,两个客户端都有机会是否再次发送/接收数据。如果C1选择重新启动其发送/接收例程,fd_set归零(使用 FD_ZERO() 宏)并且 listenfd再次放入 fd_set与先前调用的 select() 关联的变量。问题是,如果 C2尝试与 C1 建立新连接,第二个connect()不构成 select()进程在 C1 ,即使connect()调用电话 C1成功了。如果第三个客户端 (C3) 尝试 connect(),则不会发生这种情况。至C1 .

我想要了解的是,如何关闭与客户端的连接并在不同时间与同一客户端打开新连接。请注意,我不希望客户端在发送/接收例程完成后保留首次创建的连接。我想与两个客户端创建新连接。

这是客户端代码,请注意,我省略了代码中明显或无用的部分:

int nwrite,nread,servsock,listenfd,clsock[10],mastfd,maxfd,s=0,t=0,i=0,j=0;
int act,count=0;
for (i=0;i<10;i++)
clsock[i]=socket(PF_INET,SOCK_STREAM,0); //clsock is an array of sockets. Each time C2 tries to connect to a generic C1 client, it uses the clsock[count] int. count is incremented everytime a connection is closed.
for (i=0;i<10;i++)
if(setsockopt(clsock[i],SOL_SOCKET,SO_REUSEADDR,(char *)&opt2,sizeof(opt2))<0)
{
perror("setsockopt");
exit(-1);
}
listenfd=socket(PF_INET,SOCK_STREAM,0); //this is the listening socket
if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt))<0)
{
perror("setsockopt");
exit(-1);
}
if (listenfd<0)
{
perror("Listenfd: ");
exit(-1);
}

if (bind(listenfd,(struct sockaddr*)&cl2addr,sizeof(cl2addr))<0)
{
perror("Binding: ");
exit(-1);
}
if (listen(listenfd,100)<0)
{
perror("Listening: ");
exit(-1);
}
do
{
do
{
FD_ZERO(&readfd);
FD_SET(STDIN_FILENO,&readfd);
FD_SET(listenfd,&readfd); //the listenfd socket is added
FD_SET(servsock,&readfd);
[... Maxfd and the elaps structure are set....]
act=select(maxfd,&readfd,NULL,NULL,&elaps); //maxfd is calculated in another piece of code. I'm sure it is right.
system("reset");
if (FD_ISSET(listenfd,&readfd)) //when the listen procs, the loop ends for C1.
{
[...exits from the first do-while loop...]
}
if (FD_ISSET(STDIN_FILENO,&readfd)) //this is where c2 exits from the loop
{
s=1;
do some things here.
}
[.....some useless code here .....]
}
while (s!=1); //this is the condition used by c1/c2 to exit the loop
if (t==1) //this is what C1 runs, having t=1.
{
if ((mastfd=accept(listenfd,(struct sockaddr *) &cl2addr,&cllen))<0) //C1 accepts a generic connection
{
perror("Accept: ");
exit(-1);
}
[....do some things...]
if (close(mastfd)<0) //Once done, it closes the actually connected socket
{
perror("Error closing mastfd");
_exit(-1);

}
}
else //this is what C2 runs
{
claddr.sin_addr.s_addr=inet_addr(ipbuff); // ipbuff is C1 port
claddr.sin_port=htons(sprt); //sprt is C1 port
if (connect(clsock[count],(struct sockaddr *) &claddr,sizeof(claddr))<0) //create a connection between C1 and C2
{
perror("Connect: ");
printf("ERROR: %s",strerror(errno));
exit(-1);
}
[....do some things...]
if (close(clsock[count])<0)
{
perror("Error closing socket!");
_exit(-1);
}
count++; //increment count to be able to create a new connection and not to re-use the same socket in the clsock[count] array.
}
if (menu==1)
{
memset(&claddr,0,sizeof(claddr)); //this was when my brain was about to pop off
fflush(stdin);
fflush(stdout);
t=0;
s=0;
num_usr=0;
system("reset");
FD_ZERO(&readfd); //this is when my brain totally popped off
FD_CLR(listenfd,&readfd);
FD_CLR(servsock,&readfd);
FD_CLR(STDIN_FILENO,&readfd);
FD_SET(listenfd,&readfd);
FD_SET(servsock,&readfd);
FD_SET(STDIN_FILENO,&readfd);
}
} while (menu==1)

谢谢大家,如果问题提出或写得不好,请告诉我。我很抱歉我的经验不足和我的英语,我刚刚开始网络编程。预先非常感谢您的帮助。

最佳答案

在为 select() 准备 readfd 时,我没有看到任何计算新 maxfd 值的代码。调用 select() 时,maxfd 必须是所有提供的 fd_set 中最高描述符的值 + 1。没有显示每次重置 readfd 时计算 maxfd 的代码。你需要做这样的事情:

FD_ZERO(&readfd);
FD_SET(STDIN_FILENO, &readfd);
maxfd = STDIN_FILENO;
FD_SET(listenfd, &readfd);
maxfd = max(listenfd, maxfd);
FD_SET(servsock, &readfd);
maxfd = max(servsock, maxfd);

act = select(maxfd+1, &readfd, NULL, NULL, &elaps);

另请记住,在某些系统上,select() 会修改 timeval 结构以报告 select() 后剩余的时间量> 退出,因此每次调用 select() 时都应该重置 elaps

关于c - 监听()和选择(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43847560/

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