tcp.c文件的tcp_listen_select函数(14)

tcp.c文件的tcp_listen_select函数

    978计划工作组 2009-8-25

    1函数源码

    /*

     * LISTEN is a special case for select..

     */

    static int tcp_listen_select(struct sock *sk, int sel_type, select_table *wait)

    {

     if (sel_type == SEL_IN) {

     int retval;

    

     sk->inuse = 1;

     retval = (tcp_find_established(sk) != NULL);

     release_sock(sk);

     if (!retval)

     select_wait(&master_select_wakeup,wait);

     return retval;

     }

     return 0;

    }

    2函数用途

    用于判断监听套接字接收队列中是否有已经与远端通信端完成建立的套接字存在。

    3调用关系

    4语句注释

    4.1 static int tcp_listen_select(struct sock *sk, int sel_type, select_table *wait)

    sk:侦听套接字。

    sel_type:探测类型。

    4.2 if (sel_type == SEL_IN) {

    SEL_IN:宏值为1,探测是否有数据可读取,相关宏还有SEL_EX和SEL_OUT。

    4.3 sk->inuse = 1;

     retval = (tcp_find_established(sk) != NULL);

     release_sock(sk);

    skb->inuse:为1表示此sock结构处于忙状态。

    release_sock:网络层模块在将一个数据包传递给传输层模块处理时(tcp_rcv),如果当前对应的套接字正忙,则将数据包插入到sock 结构back_log 队列中。但插入该队列中的数据包并不能算是被接收,该队列中的数据包需要进行一系列处理后插入receive_queue 接收队列中时,才算是完成接收。而release_sock 函数就是从back_log 中取数据包重新调用tcp_rcv 函数对数据包进行接收。所谓back_log 队列只是数据包暂居之所,不可久留,所以也就必须对这个队列中数据包尽快进行处理,那么也就表示必须对release_sock 函数进行频繁调用。

    tcp_find_established:参见《tcp.c文件的tcp_find_established函数(2).doc》。

    4.4 if (!retval)

     select_wait(&master_select_wakeup,wait);

    select_wait:将当前执行进程插入到master_select_eakeup队列的头部。

    master_select_wakeup:等待对列或称休眠对列,是wait_queue结构指针类型。

    wait:select_table_struct类型,select_wait函数通过wait获得当前进程的信息。

    

    

    

转自: http://os.chinaunix.net/a2009/0825/997/000000997333.shtml

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`tcp_server_poll()` 函数通常用于在 TCP 服务器中处理客户端连接。它的作用是检查当前有没有待处理的客户端连接请求或者已经建立连接的客户端是否有数据待处理。它可以通过使用 `select()` 或者 `poll()` 系统调用来实现。下面是一个使用 `poll()` 的例子: ```c #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <poll.h> #define MAX_CLIENTS 10 #define BUFFER_SIZE 4096 int main(int argc, char *argv[]) { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0}; // 创建 TCP socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置 socket 地址可重用 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); // 绑定 socket 地址 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听客户端连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } struct pollfd clients[MAX_CLIENTS]; clients[0].fd = server_fd; clients[0].events = POLLIN; int n_clients = 1; while (1) { // 等待客户端连接或者数据到达 int activity = poll(clients, n_clients, -1); if (activity < 0) { perror("poll failed"); exit(EXIT_FAILURE); } // 处理新的客户端连接请求 if (clients[0].revents & POLLIN) { if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } printf("New client connected\n"); if (n_clients == MAX_CLIENTS) { printf("Too many clients\n"); close(new_socket); } else { clients[n_clients].fd = new_socket; clients[n_clients].events = POLLIN; n_clients++; } } // 处理已经建立连接的客户端发送的数据 for (int i = 1; i < n_clients; i++) { if (clients[i].revents & POLLIN) { valread = read(clients[i].fd, buffer, BUFFER_SIZE); if (valread == 0) { // 客户端关闭连接 close(clients[i].fd); printf("Client disconnected\n"); clients[i] = clients[n_clients-1]; n_clients--; } else { // 处理客户端发送的数据 printf("%s\n", buffer); send(clients[i].fd, buffer, strlen(buffer), 0); memset(buffer, 0, BUFFER_SIZE); } } } } return 0; } ``` 在 `main()` 函数中,首先创建一个 TCP socket,并设置 socket 地址可重用。然后,绑定 socket 地址,并开始监听客户端连接。 接下来,创建一个 `pollfd` 数组,用于存储所有的客户端 socket 描述符。将 `server_fd` 添加到数组中,并设置 `POLLIN` 事件,这样当有新的客户端连接请求到达时,就会触发 `POLLIN` 事件。 在 `while` 循环中,调用 `poll()` 等待客户端连接或者数据到达。如果 `POLLIN` 事件触发并且是来自 `server_fd` 的,说明有新的客户端连接请求到达,需要调用 `accept()` 来接受连接,并将新的客户端 socket 描述符添加到 `pollfd` 数组中。如果已经达到了最大客户端数,就需要关闭新的连接。如果是已经建立连接的客户端有数据到达,就需要读取数据,处理数据,并将响应数据发送回客户端。如果客户端关闭了连接,需要将其从 `pollfd` 数组中删除。 需要注意的是,`poll()` 函数的最后一个参数表示超时时间。如果设置为 -1,则表示一直等待直到有事件触发;如果设置为 0,则表示立即返回,不等待事件。如果设置为一个正整数,则表示等待指定的毫秒数后返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值