In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
(previous address) when we used socket to complete a small experiment of a server corresponding to multiple clients, for TCP connections, we had to create a new process to communicate with the new clients. That means that there are 1000 server processes out of 1000 clients, which is obviously impractical. If we can put the file descriptor to be monitored into a collection in advance, once one of the events occurs (whether it is a connection or communication), we can deal with it. This way, it will be much more convenient. So, let's learn about IO reuse today.
1 five Icano Model blocking Icano non-blocking I/OI/O Multiplexing (select and poll) signals drive Ipicuro Asynchronous Imato O blocking IO
The most popular Iripple O model is the blocking Iripple O model, and by default, all sockets are blocked.
Non-blocking IO
IO reuse
Signal driven IO
Asynchronous IO
2 I use O multiplexing
We can be notified if one or more of the Iamp O conditions are met (for example, when the input is ready to be read, or when the descriptor can take on more output). This capability is called Imax O reuse and is supported by the functions select and poll.
When a client processes multiple descriptors and a client processes multiple sockets at the same time, if a tcp server has to deal with both listening sockets and connection sockets, if a server has to deal with TCP Also need to deal with UDPselect / * According to POSIX.1-2001 * / # include / * According to earlier standards * / # include # include # include int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) Void FD_CLR (int fd, fd_set * set); / / remove a descriptor int FD_ISSET (int fd, fd_set * set) from the collection; / / whether the descriptor is void FD_SET (int fd, fd_set * set) in the collection; / / add a descriptor to the collection void FD_ZERO (fd_set * set) / / clear the descriptor set function: the function allows the process to instruct the kernel to wait for any one of multiple events to occur, and to wake up the process only after one or more events occur or after a specified time has elapsed
Provides immediate response to multiple socket read and write event parameters: nfds: the largest file descriptor in the collection + 1 (specifies the number of description words to be tested, its value is the maximum description word to be tested plus 1, description words 0, 1, 2... . All the way up to nfds is tested) readfds: to check the container for reading events writefds: to check the containers for writing events timeout: timeout return value: return the number of triggered sockets
The middle three parameters readset, writeset, and exceptset specify the description words that we want the kernel to test for read, write, and exception conditions.
If we are not interested in a condition, the corresponding parameter in these three parameters can be set to the null pointer timeout parameter
The structure of time is as follows:
Struct timeval (long tv_sec; / / s long tv_usec;// microseconds)
There are three possibilities for timeout parameters
Wait forever: return only when a description word is ready for the timeval O, for this reason, we set the timeout to a null pointer to wait for a fixed time: when a description word is ready, it returns, but does not exceed the number of seconds and microseconds specified in the timeval structure referred to by the description parameter.
Do not wait at all: return immediately after checking the description word, which is called polling. The value of timer must be 0
Fd_set parameter
Select uses a descriptor set, which is typically an array of integers, with each bit in each number corresponding to a descriptor.
Use proc
Use select to complete the previous socket test, the process is as follows:
The client code remains the same.
# include
< sys/types.h># include
< sys/socket.h># include
< netinet/in.h>/ / sockaddr_in#include
< stdio.h># include
< string.h>/ / TCPint main () {int fd; int ret; int addrLen; char acbuf [20] = "; struct sockaddr_in serAddr = {0}; struct sockaddr_in myAddr = {0}; / / 1.socket (); fd = socket (PF_INET,SOCK_STREAM,0); if (fd = =-1) {perror (" socket "); return-1;} / / 2. Address to connect to the connect () server serAddr.sin_family = AF_INET; serAddr.sin_port = htons (1234); serAddr.sin_addr.s_addr = inet_addr ("192.168.159.5"); ret = connect (fd, (struct sockaddr *) & serAddr,sizeof (struct sockaddr_in)); if (ret = =-1) {perror ("connect"); return-1 } / / get your own address addrLen = sizeof (struct sockaddr_in); ret = getsockname (fd, (struct sockaddr *) & myAddr,&addrLen); if (ret = =-1) {perror ("getsockname"); return-1 } printf ("client---ip:% s, port:% d\ n",\ inet_ntoa (myAddr.sin_addr), ntohs (myAddr.sin_port)); / / 3. Communications while (1) {printf ("send:"); fflush (stdout); scanf ("% s", acbuf); if (strcmp (acbuf, "exit") = = 0) {break;} write (fd,acbuf,strlen (acbuf));} / / 4.close () close (fd); return 0;}
Server side:
Select.c
# include
< sys/types.h># include
< sys/socket.h># include
< netinet/in.h>/ / sockaddr_in # include
< stdio.h># include
< string.h># include
< signal.h># include
< sys/select.h># include
< unistd.h># include
< sys/time.h>/ / TCP int main () {int fd; int clientfd; int ret; pid_t pid; int i; int maxfd; / / current maximum socket int nEvent; fd_set set = {0}; / / listen on collection fd_set oldset = {0} / / store all file descriptors struct timeval time = {0}; int reuse = 0; char acbuf [20] = ""; char client_addr [100] = ""; struct sockaddr_in addr = {0}; / / own address struct sockaddr_in clientAddr = {0}; / / the address of the connected client int addrLen = sizeof (struct sockaddr_in) Signal (SIGCHLD,SIG_IGN); / / 1.socket () fd = socket (PF_INET,SOCK_STREAM,0); if (fd = =-1) {perror ("socket"); return-1;} / / No active socket still exists and port binding is disabled with error: address already in use. / / caused by TCP socket TIME_WAIT. Bind returns EADDRINUSE, which retains if for 2-4 minutes (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, & reuse, sizeof (reuse)).
< 0) { perror("setsockopet error\n"); return -1; } //2.bind() addr.sin_family = AF_INET; addr.sin_port = htons(1234); addr.sin_addr.s_addr = inet_addr("192.168.159.5"); ret = bind(fd,(struct sockaddr *)&addr,addrLen); if(ret == -1) { perror("bind"); return -1; } //3.listen() ret = listen(fd,10); if(ret == -1) { perror("listen"); return -1; } //创建监听集合 FD_ZERO(&oldset); FD_SET(fd,&oldset); //maxfdp1:当前等待的最大套接字。比如:当前fd的值=3,则最大的套接字就是3 //所以每当有客户端连接进来,就比较一下文件描述符 maxfd = fd; //select //select之前,set放的是所有要监听的文件描述符;{3,4,5} //select之后,set只剩下有发生事件的文件描述符。{3} while(1) { set = oldset; printf("before accept.\n"); time.tv_sec = 5; nEvent = select(maxfd + 1,&set,NULL,NULL,&time); //返回文件描述符的个数(即事件的个数) printf("after accept.%d\n",nEvent); if(nEvent == -1) { perror("select"); return -1; } else if(nEvent == 0) //超时 { printf("time out"); return 1; } else { //有事件发生 //判断是否是客户端产生的事件 for(i = 0 ; i maxfd) { maxfd = clientfd; } } else { memset(acbuf,0,20); if(read(i,acbuf,20) == 0) //客户端退出 { close(i); //还要从集合里删除 FD_CLR(i,&oldset); } else printf("receive: %s\n",acbuf); } } } } } return 0; }epoll epoll用到的函数有以下几个: #include int epoll_create(int size);//创建epoll int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);//操作函数 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); 事件集合的结构体:(here, also note that the timeout parameter of epoll is int, in us.)
Use proc
# include # include # include / / sockaddr_in # include # include / / epoll / / epoll_wait () epoll_creat () epoll_ctl () / / TCP int main () {int fd; int clientfd; int ret; pid_t pid Int i; int epfd; int nEvent; struct epoll_event event = {0}; struct epoll_event rtl_events [20] = {0}; / / event result set int reuse = 0; char acbuf [20] = ""; char client_addr [20] = ""; struct sockaddr_in addr = {0} / / own address struct sockaddr_in clientAddr = {0}; / / address of the connected client int addrLen = sizeof (struct sockaddr_in); signal (SIGCHLD,SIG_IGN); / / 1.socket () fd = socket (PF_INET,SOCK_STREAM,0) If (fd = =-1) {perror ("socket"); return-1;} / an inactive socket still exists and port binding is disabled with error: address already in use. / / caused by the TCP socket TIME_WAIT. Bind returns EADDRINUSE, which retains 2-4 minutes if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, & reuse, sizeof (reuse)) < 0) {perror ("setsockopet error\ n"); return-1 } / / 2.bind () addr.sin_family = AF_INET; addr.sin_port = htons (1234); addr.sin_addr.s_addr = inet_addr ("192.168.159.5"); ret = bind (fd, (struct sockaddr *) & addr,addrLen) If (ret = =-1) {perror ("bind"); return-1;} / / 3.listen () ret = listen (fd,10); if (ret = =-1) {perror ("listen"); return-1 } epfd = epoll_create (1000); / / simultaneous listening file descriptor event.data.fd = fd; event.events = EPOLLIN; / / read epoll_ctl (epfd,EPOLL_CTL_ADD,fd, & event) While (1) {/ / nEvent = epoll_wait (epfd,rtl_events,20,-1); / /-1: blocking 0: non-blocking nEvent = epoll_wait (epfd,rtl_events,20,5000); if (nEvent = =-1) {perror ("epoll_wait") Return-1;} else if (nEvent = = 0) {printf ("time out.");} else {/ / if an event occurs, deal with for immediately (I = 0) I < nEvent;i++) {/ / if it is a server fd if (rtl_ events [I] .data.fd = = fd) {clientfd = accept (fd, (struct sockaddr *) & clientAddr,&addrLen) / / add event.data.fd = clientfd; event.events = EPOLLIN; / / read epoll_ctl (epfd,EPOLL_CTL_ADD,clientfd,&event) Printf ("client ip:%s, port:%u\ n", inet_ntoa (clientAddr.sin_addr), ntohs (clientAddr.sin_port)) } else {/ / otherwise client fd memset (acbuf,0,20); ret = read (rtl_ events [I] .data.fd, acbuf,20) Printf ("% d\ n", ret); if (ret = = 0) / / client exit {close (rtl_ events [I] .data.fd) / / remove epoll_ctl (epfd,EPOLL_CTL_DEL,rtl_ events [I] .data.fd, NULL) from the collection;} else printf ("receive:% s\ n", acbuf) } return 0;}
The running result is the same as before, sending and receiving normally.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.