select在并发中的两点限制与poll函数的使用

用select实现的并发服务器,能达到的并发数,受两方面限制:

一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。

select中的fd_set集合容量的限制(FD_SETSIZE) ,这需要重新编译内核。//这个不能通过调整内核参数来限制  FD_SETSIZE宏等于1024在一个头文件中设置 改变它需要重新编译内核。

ulinit   -n来查询最大文件描述符 得到1024   可以通过sudo  bash 换位root用户    ulimit  -n  2048进行修改最大文件描述符    man   getrlimit   其中三个被标准输入 标准输出  标准错误  监听套接字给占用  实际使用只有1020个文件描述符

poll函数没有FD_SETSIZE的限制(与select用法差不多)

q#include <poll.h>

qint poll(struct pollfd *fds, nfds_t nfds, int timeout);我们要关注的I/O与事件加入到第一个参数中即可   第二个I/O的个数   第三个参数是超时的时间

只受一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。pollfd一个结构体内含有fd,events,return  events.可通过man   poll查询。

pollsrv.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <sys/wait.h>

#include <poll.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

ssize_t readn(int fd, void *buf, size_t count)

{

size_t nleft = count;

ssize_t nread;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nread = read(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nread == 0)

return count - nleft;

bufp += nread;

nleft -= nread;

}

return count;

}

ssize_t writen(int fd, const void *buf, size_t count)

{

size_t nleft = count;

ssize_t nwritten;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nwritten = write(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nwritten == 0)

continue;

bufp += nwritten;

nleft -= nwritten;

}

return count;

}

ssize_t recv_peek(int sockfd, void *buf, size_t len)

{

while (1)

{

int ret = recv(sockfd, buf, len, MSG_PEEK);

if (ret == -1 && errno == EINTR)

continue;

return ret;

}

}

ssize_t readline(int sockfd, void *buf, size_t maxline)

{

int ret;

int nread;

char *bufp = buf;

int nleft = maxline;

while (1)

{

ret = recv_peek(sockfd, bufp, nleft);

if (ret < 0)

return ret;

else if (ret == 0)

return ret;

nread = ret;

int i;

for (i=0; i<nread; i++)

{

if (bufp[i] == ‘\n‘)

{

ret = readn(sockfd, bufp, i+1);

if (ret != i+1)

exit(EXIT_FAILURE);

return ret;

}

}

if (nread > nleft)

exit(EXIT_FAILURE);

nleft -= nread;

ret = readn(sockfd, bufp, nread);

if (ret != nread)

exit(EXIT_FAILURE);

bufp += nread;

}

return -1;

}

void echo_srv(int conn)

{

char recvbuf[1024];

while (1)

{

memset(recvbuf, 0, sizeof(recvbuf));

int ret = readline(conn, recvbuf, 1024);

if (ret == -1)

ERR_EXIT("readline");

if (ret == 0)

{

printf("client close\n");

break;

}

fputs(recvbuf, stdout);

writen(conn, recvbuf, strlen(recvbuf));

}

}

void handle_sigchld(int sig)

{

/*    wait(NULL);*/

while (waitpid(-1, NULL, WNOHANG) > 0)

;

}

void handle_sigpipe(int sig)

{

printf("recv a sig=%d\n", sig);

}

int main(void)

{

int count = 0;

signal(SIGPIPE, handle_sigpipe);

signal(SIGCHLD, handle_sigchld);

int listenfd;

if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)

ERR_EXIT("socket");

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

int on = 1;

if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)

ERR_EXIT("setsockopt");

if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("bind");

if (listen(listenfd, SOMAXCONN) < 0)

ERR_EXIT("listen");

struct sockaddr_in peeraddr;

socklen_t peerlen;

int conn;

int i;

struct pollfd client[2048];

int maxi = 0;

for (i=0; i<2048; i++)

client[i].fd = -1;

int nready;

client[0].fd = listenfd;

client[0].events = POLLIN;

while (1)

{

nready = poll(client, maxi+1, -1);

if (nready == -1)

{

if (errno == EINTR)

continue;

ERR_EXIT("select");

}

if (nready == 0)

continue;

if (client[0].revents & POLLIN)

{

peerlen = sizeof(peeraddr);

conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen);

if (conn == -1)

ERR_EXIT("accept");

for (i=0; i<2048; i++)

{

if (client[i].fd < 0)

{

client[i].fd = conn;

if (i > maxi)

maxi = i;

break;

}

}

if (i == 2048)

{

fprintf(stderr, "too many clients\n");

exit(EXIT_FAILURE);

}

printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

printf("count = %d\n", ++count);

client[i].events = POLLIN;

if (--nready <= 0)

continue;

}

for (i=1; i<=maxi; i++)

{

conn = client[i].fd;

if (conn == -1)

continue;

if (client[i].events & POLLIN)

{

char recvbuf[1024] = {0};

int ret = readline(conn, recvbuf, 1024);

if (ret == -1)

ERR_EXIT("readline");

if (ret == 0)

{

printf("client close\n");

client[i].fd = -1;

close(conn);

}

fputs(recvbuf, stdout);

writen(conn, recvbuf, strlen(recvbuf));

if (--nready <= 0)

break;

}

}

}

return 0;

}

makefile:

.PHONY:clean all

CC=gcc

CFLAGS=-Wall -g

BIN= echocli  conntest pollsrv

all:$(BIN)

%.o:%.c

$(CC) $(CFLAGS) -c $< -o [email protected]

clean:

rm -f *.o $(BIN)

echocli.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

ssize_t readn(int fd, void *buf, size_t count)

{

size_t nleft = count;

ssize_t nread;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nread = read(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nread == 0)

return count - nleft;

bufp += nread;

nleft -= nread;

}

return count;

}

ssize_t writen(int fd, const void *buf, size_t count)

{

size_t nleft = count;

ssize_t nwritten;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nwritten = write(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nwritten == 0)

continue;

bufp += nwritten;

nleft -= nwritten;

}

return count;

}

ssize_t recv_peek(int sockfd, void *buf, size_t len)

{

while (1)

{

int ret = recv(sockfd, buf, len, MSG_PEEK);

if (ret == -1 && errno == EINTR)

continue;

return ret;

}

}

ssize_t readline(int sockfd, void *buf, size_t maxline)

{

int ret;

int nread;

char *bufp = buf;

int nleft = maxline;

while (1)

{

ret = recv_peek(sockfd, bufp, nleft);

if (ret < 0)

return ret;

else if (ret == 0)

return ret;

nread = ret;

int i;

for (i=0; i<nread; i++)

{

if (bufp[i] == ‘\n‘)

{

ret = readn(sockfd, bufp, i+1);

if (ret != i+1)

exit(EXIT_FAILURE);

return ret;

}

}

if (nread > nleft)

exit(EXIT_FAILURE);

nleft -= nread;

ret = readn(sockfd, bufp, nread);

if (ret != nread)

exit(EXIT_FAILURE);

bufp += nread;

}

return -1;

}

void echo_cli(int sock)

{

/*

char sendbuf[1024] = {0};

char recvbuf[1024] = {0};

while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)

{

writen(sock, sendbuf, strlen(sendbuf));

int ret = readline(sock, recvbuf, sizeof(recvbuf));

if (ret == -1)

ERR_EXIT("readline");

else if (ret == 0)

{

printf("client close\n");

break;

}

fputs(recvbuf, stdout);

memset(sendbuf, 0, sizeof(sendbuf));

memset(recvbuf, 0, sizeof(recvbuf));

}

close(sock);

*/

fd_set rset;

FD_ZERO(&rset);

int nready;

int maxfd;

int fd_stdin = fileno(stdin);

if (fd_stdin > sock)

maxfd = fd_stdin;

else

maxfd = sock;

char sendbuf[1024] = {0};

char recvbuf[1024] = {0};

int stdineof = 0;

while (1)

{

if (stdineof == 0)

FD_SET(fd_stdin, &rset);

FD_SET(sock, &rset);

nready = select(maxfd+1, &rset, NULL, NULL, NULL);

if (nready == -1)

ERR_EXIT("select");

if (nready == 0)

continue;

if (FD_ISSET(sock, &rset))

{

int ret = readline(sock, recvbuf, sizeof(recvbuf));

if (ret == -1)

ERR_EXIT("readline");

else if (ret == 0)

{

printf("server close\n");

break;

}

fputs(recvbuf, stdout);

memset(recvbuf, 0, sizeof(recvbuf));

}

if (FD_ISSET(fd_stdin, &rset))

{

if (fgets(sendbuf, sizeof(sendbuf), stdin) == NULL)

{

stdineof = 1;

/*

close(sock);

sleep(5);

exit(EXIT_FAILURE);

*/

shutdown(sock, SHUT_WR);

}

else

{

writen(sock, sendbuf, strlen(sendbuf));

memset(sendbuf, 0, sizeof(sendbuf));

}

}

}

}

void handle_sigpipe(int sig)

{

printf("recv a sig=%d\n", sig);

}

int main(void)

{

/*

signal(SIGPIPE, handle_sigpipe);

*/

signal(SIGPIPE, SIG_IGN);

int sock;

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

ERR_EXIT("socket");

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("connect");

struct sockaddr_in localaddr;

socklen_t addrlen = sizeof(localaddr);

if (getsockname(sock, (struct sockaddr*)&localaddr, &addrlen) < 0)

ERR_EXIT("getsockname");

printf("ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));

echo_cli(sock);

return 0;

}

conntest.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

int main(void)

{

int count = 0;

while(1)

{

int sock;

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

{

sleep(4);

ERR_EXIT("socket");

}

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("connect");

struct sockaddr_in localaddr;

socklen_t addrlen = sizeof(localaddr);

if (getsockname(sock, (struct sockaddr*)&localaddr, &addrlen) < 0)

ERR_EXIT("getsockname");

printf("ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));

printf("count = %d\n", ++count);

}

return 0;

}

select在并发中的两点限制与poll函数的使用

时间: 2024-10-08 10:19:28

select在并发中的两点限制与poll函数的使用的相关文章

将Excel导入DataGridView 中的"select * from [Sheet1$]"中[ ]里面表单名的动态获取

Sheet1$是Excel默认的第一个表名,如果改动:select * from [Sheet1$]"将查询失败,因此应根据选择自动获取excel表名: 1 OpenFileDialog ofd = new OpenFileDialog(); //选择文件路径 2 ofd.Title = "Excel文件"; 3 ofd.FileName = ""; 4 ofd.Filter = "Excel文件(*.xls)| *.xls"; 5 s

2D和3D空间中计算两点之间的距离

自己在做游戏的忘记了Unity帮我们提供计算两点之间的距离,在百度搜索了下. 原来有一个公式自己就写了一个方法O(∩_∩)O~,到僵尸到达某一个点之后就向另一个奔跑过去 /// <summary> /// 3维中如何计算两点之间的距离 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// &l

【转】Java并发中正确使用volatile

Java并发中正确使用volatile 原文链接 http://ifeve.com/how-to-use-volatile/ 作者:一粟   整理和翻译自Twitter实时搜索的PPT 前几天并发编程群里有同学对volatile的用法提出了疑问,刚好我记得Twitter有关实时搜索的这个PPT对这个问题解释的很清晰并有一个实际的应用场景,于是周末把这个问题摘录了一些和并发相关的内容如下: 并发 – 定义 悲观锁 – Pressimistic locking 一个线性在执行一个操作时持有对一个资源

03_MyBatis基本查询,mapper文件的定义,测试代码的编写,resultMap配置返回值,sql片段配置,select标签标签中的内容介绍,配置使用二级缓存,使用别名的数据类型,条件查询ma

 1 PersonTestMapper.xml中的内容如下: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace:命名空间

Java线程并发中常见的锁--自旋锁 偏向锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作.也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作了,从而节约了操作时间,如果在此之间有其他的线程进行了锁请求,则锁退出偏向模式.在JVM中使用-XX:+UseBiasedLocking pac

Java线程并发中常见的锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作.也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作了,从而节约了操作时间,如果在此之间有其他的线程进行了锁请求,则锁退出偏向模式.在JVM中使用-XX:+UseBiasedLocking pac

Floyd-Warshall求图中任意两点的最短路径

原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短路径(前提是存在此路径): 2:A先通过其他点,再由其他点到B. 我们并不知道A是否需要通过其他点间接到达B,所以只能比较,用A到B的直接路径和A先通过其他点 再间接到达B的路径长度进行比较,然后更新为较小值. 上图中若要求顶点4到顶点3的最短路径,可以比较顶点4直接到3的路径和顶点4先到1,再到3

java高并发系列 - 第32天:高并发中计数器的实现方式有哪些?

这是java高并发系列第32篇文章. java环境:jdk1.8. 本文主要内容 4种方式实现计数器功能,对比其性能 介绍LongAdder 介绍LongAccumulator 需求:一个jvm中实现一个计数器功能,需保证多线程情况下数据正确性. 我们来模拟50个线程,每个线程对计数器递增100万次,最终结果应该是5000万. 我们使用4种方式实现,看一下其性能,然后引出为什么需要使用LongAdder.LongAccumulator. 方式一:synchronized方式实现 package

Golang并发中channel的分析

问题:面对并发问题,是用channel解决,还是用Mutex解决? 如果自己心里还没有清晰的答案,那就读下这篇文章,你会了解到: 使用channel解决并发问题的核心思路和示例 channel擅长解决什么样的并发问题,Mutex擅长解决什么样的并发问题 一个并发问题该怎么入手解解决 一个重要的plus思维 前戏 前面很多篇的文章都在围绕channel介绍,而只有前一篇sync的文章介绍到了Mutex,不是我偏心,而是channel在Golang是first class级别的,设计在语言特性中的,