日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2高并发服务器:多路IO之poll

發布時間:2024/9/27 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2高并发服务器:多路IO之poll 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


1 poll

A 依賴的頭文件

#include <poll.h>

B 函數聲明

int poll(struct pollfd *fds, nfds_t nfds,int timeout);

?

struct pollfd {

int fd; /* 文件描述符*/

short events; /* 監控的事件*/

short revents; /* 監控事件中滿足條件返回的事件*/

};

POLLIN普通或帶外優先數據可讀,POLLRDNORM |POLLRDBAND

POLLRDNORM-數據可讀

POLLRDBAND-優先級帶數據可讀

POLLPRI 高優先級可讀數據

?

POLLOUT普通或帶外數據可寫

POLLWRNORM-數據可寫

POLLWRBAND-優先級帶數據可寫

?

POLLERR 發生錯誤

POLLHUP 發生掛起

POLLNVAL 描述字不是一個打開的文件

?

nfds監控數據中有多少文件描述符需要被監控

timeout 毫秒級等待

-1:阻塞等,#defineINFTIM -1 Linux中沒有定義此宏

0 :立即返回,不阻塞進程

>0:等待指定毫秒數,如當前系統時間精度不夠毫秒,向上取值

?

如果不再監控某個文件描述符時,可以把pollfd中,fd設置為-1poll不再監控此pollfd,下次返回時,把revents設置為0

??? ppollGNU定義了ppoll(POSIX標準),可以支持設置信號屏蔽字,大家可參考poll模型自行實現C/S

#define _GNU_SOURCE /* Seefeature_test_macros(7) */

#include <poll.h>

int ppoll(struct pollfd *fds, nfds_t nfds,

const struct timespec *timeout_ts, constsigset_t *sigmask);

?

案例說明:

Server.c

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<poll.h>

#include<errno.h>

#include<ctype.h>

#include"wrap.h"

?

#define MAXLINE 80

#define SERV_PORT 8000

#define OPEN_MAX 1024

?

int main(void)

{

??? int i, j, maxi, listenfd, connfd, sockfd;

??? int nready;

??? ssize_t n;

??? char buf[MAXLINE], str[INET_ADDRSTRLEN];

??? socklen_t clilen;

??? struct pollfd client[OPEN_MAX];

??? struct sockaddr_in cliaddr, servaddr;

??? listenfd = Socket(AF_INET, SOCK_STREAM, 0);

??? bzero(&servaddr, sizeof(servaddr));

??? servaddr.sin_family = AF_INET;

??? servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

??? servaddr.sin_port = htons(SERV_PORT);

??? Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

??? Listen(listenfd, 20);

??? client[0].fd = listenfd;

??? client[0].events = POLLRDNORM; /* listenfd監聽普通讀事件*/

??? for (i = 1; i < OPEN_MAX; i++)

??????? client[i].fd = -1; /* -1初始化client[]里剩下元素*/

??? maxi = 0; /* client[]數組有效元素中最大元素下標*/

??? for ( ; ; ) {

??????? nready = poll(client, maxi+1, -1); /* 阻塞*/

??????? if (client[0].revents & POLLRDNORM) { /* 有客戶端鏈接請求*/

??????????? clilen = sizeof(cliaddr);

??????????? connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

??????????? printf("received from %s at PORT %d\n",

??????????????????? inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),

??????????????????? ntohs(cliaddr.sin_port));

??????????? for (i = 1; i < OPEN_MAX; i++)

??????????????? if (client[i].fd < 0) {

??????????????????? client[i].fd = connfd; /* 找到client[]中空閑的位置,存放accept返回的connfd */

??????????????????? break;

??????????????? }

??????????? if (i == OPEN_MAX)

??????????????? perr_exit("too many clients");

??????????? client[i].events = POLLRDNORM; /* 設置剛剛返回的connfd,監控讀事件*/

??????????? if (i > maxi)

??????????????? maxi = i; /* 更新client[]中最大元素下標*/

??????????? if (--nready <= 0)

??????????????? continue; /* 沒有更多就緒事件時,繼續回到poll阻塞*/

??????? }

??????? for (i = 1; i <= maxi; i++) { /* 檢測client[] */

??????????? if ( (sockfd = client[i].fd) < 0)

??????????????? continue;

??????????? if (client[i].revents & (POLLRDNORM | POLLERR)) {

??????????????? if ( (n = Read(sockfd, buf, MAXLINE)) < 0) {

????????????? ??????if (errno == ECONNRESET) { /* 當收到RST標志時*/

??????????????????????? /* connection reset by client */

??????????????????????? printf("client[%d] aborted connection\n", i);

??????????????????????? Close(sockfd);

??????????????????????? client[i].fd = -1;

??????????????????? } else

??????????????????????? perr_exit("read error");

??????????????? } else if (n == 0) {

??????????????????? /* connection closed by client */

??????????????????? printf("client[%d] closed connection\n", i);

??????????????????? Close(sockfd);

??????????????????? client[i].fd = -1;

??????????????? } else {

??????????????????? for (j = 0; j < n; j++)

??????????????????????? buf[j] = toupper(buf[j]);

??????????????????? Writen(sockfd, buf, n);

??????????????? }

??????????????? if (--nready <= 0)

??????????????????? break; /* no more readable descriptors */

??????????? }

??????? }

??? }

??? return 0;

}

Client.c

#include<stdio.h>

#include<string.h>

#include<unistd.h>

#include<arpa/inet.h>

#include<netinet/in.h>

#include"wrap.h"

?

#define MAXLINE 80

#define SERV_PORT 8000

?

int main(void)

{

??? struct sockaddr_in servaddr;

??? char buf[MAXLINE];

??? int sockfd,n;

?

??? sockfd = Socket(AF_INET,SOCK_STREAM,0);

?

??? bzero(&servaddr,sizeof(servaddr));

??? servaddr.sin_family = AF_INET;

??? inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);

??? servaddr.sin_port = htons(SERV_PORT);

?

??? Connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

?

??? while(fgets(buf,MAXLINE,stdin) != NULL) {

??????? Write(sockfd,buf,strlen(buf));

??????? n = Read(sockfd,buf,MAXLINE);

??????? if(n==0) {

??????????? printf("the other side has been closed\n");

??????? } else {

??????????? Write(STDOUT_FILENO,buf,n);

??????? }

??? }

?

??? Close(sockfd);

??? return 0;

}

Wrap.h

#ifndef __WRAP_H_

#define __WRAP_H_

?

void perr_exit(const char *s);

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);

void Bind(int fd, const struct sockaddr *sa, socklen_t salen);

void Connect(int fd, const struct sockaddr *sa, socklen_t salen);

void Listen(int fd, int backlog);

int Socket(int family, int type, int protocol);

ssize_t Read(int fd, void *ptr, size_t nbytes);

ssize_t Write(int fd, const void *ptr, size_t nbytes);

void Close(int fd);

ssize_t Readn(int fd, void *vptr, size_t n);

ssize_t Writen(int fd, const void *vptr, size_t n);

static ssize_t my_read(int fd, char *ptr);

ssize_t Readline(int fd, void *vptr, size_t maxlen);

?

#endif

Wrap.c

#include <stdlib.h>

#include <errno.h>

#include <sys/socket.h>

?

void perr_exit(const char *s)

{

???????? perror(s);

???????? exit(1);

}

?

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)

{

???????? int n;

?

again:

???????? if ( (n = accept(fd, sa, salenptr)) < 0) {

?????????????????? if ((errno == ECONNABORTED) || (errno == EINTR))

??????????????????????????? goto again;

?????????????????? else

??????????????????????????? perr_exit("accept error");

???????? }

???????? return n;

}

?

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)

{

???????? if (bind(fd, sa, salen) < 0)

?????????????????? perr_exit("bind error");

}

?

void Connect(int fd, const struct sockaddr *sa, socklen_t salen)

{

???????? if (connect(fd, sa, salen) < 0)

?????????????????? perr_exit("connect error");

}

?

void Listen(int fd, int backlog)

{

???????? if (listen(fd, backlog) < 0)

?????????????????? perr_exit("listen error");

}

?

int Socket(int family, int type, int protocol)

{

???????? int n;

?

???????? if ( (n = socket(family, type, protocol)) < 0)

?????????????????? perr_exit("socket error");

???????? return n;

}

?

ssize_t Read(int fd, void *ptr, size_t nbytes)

{

???????? ssize_t n;

?

again:

???????? if ( (n = read(fd, ptr, nbytes)) == -1) {

?????????????????? if (errno == EINTR)

??????????????????????????? goto again;

?????????????????? else

??????????????????????????? return -1;

???????? }

???????? return n;

}

?

ssize_t Write(int fd, const void *ptr, size_t nbytes)

{

???????? ssize_t n;

?

again:

???????? if ( (n = write(fd, ptr, nbytes)) == -1) {

?????????????????? if (errno == EINTR)

??????????????????????????? goto again;

?????????????????? else

??????????????????????????? return -1;

???????? }

???????? return n;

}

?

void Close(int fd)

{

???????? if (close(fd) == -1)

?????????????????? perr_exit("close error");

}

ssize_t Readn(int fd, void *vptr, size_t n)

{

???????? size_t? nleft;

???????? ssize_t nread;

???????? char?? *ptr;

?

???????? ptr = vptr;

???????? nleft = n;

???????? while (nleft > 0) {

?????????????????? if ( (nread = read(fd, ptr, nleft)) < 0) {

??????????????????????????? if (errno == EINTR)

???????????????????????????????????? nread = 0;

??????????????????????????? else

???????????????????????????????????? return -1;

?????????????????? } else if (nread == 0)

??????????????????????????? break;

?

?????????????????? nleft -= nread;

?????????????????? ptr += nread;

???????? }

???????? return n - nleft;

}

?

ssize_t Writen(int fd, const void *vptr, size_t n)

{

???????? size_t nleft;

???????? ssize_t nwritten;

???????? const char *ptr;

?

???????? ptr = vptr;

???????? nleft = n;

???????? while (nleft > 0) {

?????????????????? if ( (nwritten = write(fd, ptr, nleft)) <= 0) {

??????????????????????????? if (nwritten < 0 && errno == EINTR)

???????????????????????????????????? nwritten = 0;

??????????????????????????? else

???????????????????????????????????? return -1;

?????????????????? }

?

?????????????????? nleft -= nwritten;

?????????????????? ptr += nwritten;

???????? }

???????? return n;

}

static ssize_t my_read(int fd, char *ptr)

{

???????? static int read_cnt;

???????? static char *read_ptr;

???????? static char read_buf[100];

?

???????? if (read_cnt <= 0) {

again:

?????????????????? if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {

??????????????????????????? if (errno == EINTR)

???????????????????????????????????? goto again;

??????????????????????????? return -1;

?????????????????? } else if (read_cnt == 0)

??????????????????????????? return 0;

?????????????????? read_ptr = read_buf;

???????? }

???????? read_cnt--;

???????? *ptr = *read_ptr++;

???????? return 1;

}

?

ssize_t Readline(int fd, void *vptr, size_t maxlen)

{

???????? ssize_t n, rc;

???????? char??? c, *ptr;

?

???????? ptr = vptr;

???????? for (n = 1; n < maxlen; n++) {

?????????????????? if ( (rc = my_read(fd, &c)) == 1) {

??????????????????????????? *ptr++ = c;

??????????????????????????? if (c? == '\n')

???????????????????????????????????? break;

?????????????????? } else if (rc == 0) {

??????????????????????????? *ptr = 0;

??????????????????????????? return n - 1;

?????????????????? } else

??????????????????????????? return -1;

???????? }

???????? *ptr? = 0;

???????? return n;

}

?

總結

以上是生活随笔為你收集整理的2高并发服务器:多路IO之poll的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。