gpt4 book ai didi

c - 在 TCP 服务器的读/写上实现 poll()

转载 作者:太空狗 更新时间:2023-10-29 15:05:53 25 4
gpt4 key购买 nike

我需要这个服务器能够监听和建立与客户端的新连接,同时写入现有连接.. 即。异步非阻塞 i/o。我被告知要使用 poll(),但在花费大量时间试图掌握套接字编程之后,我仍然不确定如何实现 poll() 函数。

int sockfd; 

int main(int argc, char *argv[])
{
int newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;

if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");

bzero((char *) &serv_addr, sizeof(serv_addr));

portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);

clilen = sizeof(cli_addr);

while(1){
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");

// READ READ READ READ READ READ READ READ READ READ READ READ READ READ READ READ
bzero(buffer,256);
n = read(newsockfd,buffer,255);


if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);

// WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
}

return 0;

我的理解是我需要构建这样的东西:

//  Set up array of file descriptors for polling
struct pollfd ufds[2];
ufds[0].fd = sockfd;
ufds[0].events = POLLIN;

ufds[1].fd = newsockfd;
ufds[1].events = POLLOUT;

并使用 poll(ufds,2,2000);在循环内检查 sockfd 或 newsockfd 是否有任何事件,在这种情况下我使用适当的读或写。如果有人能给我一些指导,我将不胜感激。

最佳答案

内核将填充 struct pollfd 数组的 revents 字段中发生的事件。

来自手册页:

The field revents is an output parameter, filled by the kernel with the events that actually occurred. The bits returned in revents can include any of those specified in events, or one of the values POLLERR, POLLHUP, or POLLNVAL. (These three bits are meaningless in the events field, and will be set in the revents field whenever the corresponding condition is true.)

如果您想要接受连接的事件通知,那么您需要提前预留空间或为每个连接调整 struct pollfd 数组的大小。

您需要一些方法来区分监听套接字。您可以将它存储在数组的索引零中。

int i, n;

n = poll(ufds, num_fds_in_array, timeout_value);

/* errors or timeout? */
if (n < 1)
;

for (i = 0; i < num_fds_in_array; i++) {
/* were there any events for this socket? */
if (!ufds[i].revents)
continue;

/* is it our listening socket? */
if (!i) {
if (ufds[0].revents & POLLIN)
/* call accept() and add the new socket to ufds */
else
/* error */

continue;
}

/* is there incoming data on the socket? */
if (ufds[i].revents & POLLIN)
/* call recv() on the socket and decide what to do from there */
}

POLLOUT 标志用于在套接字上发送数据不会阻塞调用者时发出信号。

对于非阻塞 I/O,我会使用更强大的 API,因为它需要更多的簿记才能可靠地完成。请参阅下一段。

不幸的是,在使用 poll 时,没有空间为辅助的每个连接数据存储状态。根据您的平台,有可用的替代方案,例如。 G。用于 Linux 的 epoll,用于 *BSD 的 kqueue,以及一些用于 Windows 的选项。如果您想对上下文数据使用 poll,则必须使用可以使用文件描述符或数组索引进行搜索的数据结构。

关于c - 在 TCP 服务器的读/写上实现 poll(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19557941/

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