When I write this code, I find that many places are easily mistaken. Select may have an error, return-1.
Like what
int fd_isset (int fd,fd_set *fdset), void fd_clr (int fd,fd_set *fdset), void fd_set (int fd,fd_set *fdset); void Fd_zero (int fd,fd_set *fdset);
Several of the macros here are incoming pointers, not value passing.
The SELECT function is declared as follows:
int select (int maxfdp1,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
Usage:
1. First define good fd_set structure, and use macro Fd_zero to clear 0 processing.
2. Bind the struct and the LISTENFD with Fd_set.
3. Call SELECT. (select will always be plugged in here, listening to LISTENFD or SOCKFD (three handshake messages or data coming))
4. Detect if the incoming data is a three-time handshake, and if so, establish a connection.
5. Traverse the socket with a for from zero to detect if the incoming data is a message, and if so, receive it.
The code is as follows:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <netinet/in.h> #include <errno.h> #define Max_liste N_que 10#define max_buff_line 100#define PORT 9999 int create_socket (); int process_data (int sockfd, fd_set *global_rdfs) ; int main (int argc, char **argv) {int LISTENFD, sockfd;int i, maxfd;struct sockaddr_in cli_addr;int cli_addr_len;int err;ch Ar buff[max_buff_line];int bytes;//declares two fdset variables, fd_set global_rdfs,current_rdfs;listenfd = Create_socket ();//Clear 0 Fd_ ZERO (&GLOBAL_RDFS);//LISTENFD and Global_rdfs are associated. Fd_set (LISTENFD, &global_rdfs); maxfd = Listenfd;cli_addr_len = sizeof (CLI_ADDR); for (;;) {//Because GLOBAL_RDFS should always pay attention to listenfd//in order to ensure that the fd_set structure to read and write after the next for loop can not error//here with an alias. Current_rdfs = global_rdfs;if (err = select (Maxfd + 1, &CURRENT_RDFS, NULL, NULL, NULL)) < 0) {//program will block in select until data is available Incoming printf ("Select err:%d", err); return-1;} if (Fd_isset (LISTENFD, &CURRENT_RDFS) {//If there is data for three handshake, connect if (SOCKFD = accept (LISTENFD, struct sockaddr *) &cli_addr, &cli_addr_ Len) <0) {perror ("accept error.\n"); return-1;} printf ("Generated a new connection (sockfd:%d) \ n", SOCKFD); FD_CLR (i, ¤t_rdfs); maxfd = maxfd > sockfd? MAXFD:SOCKFD; Fd_set (SOCKFD, &global_rdfs); continue;} Traverse from 0 to Max, looking for the incoming message data for (i = 0; I <= maxfd; i++) {if (Fd_isset (i, ¤t_rdfs)) {printf ("Generate New data:");p rintf (" process_data\n ");p rintf (" I Data:%d ", i);
Note that the object of operation here must be global_rdfs.
If written as Current_rdfs, then select Error Process_data (i, &global_rdfs);}} return 0;} int process_data (int sockfd, fd_set *global_rdfs) {char buff[max_buff_line];int bytes;bzero (buff, max_buff_line); bytes = recv (SOCKFD, Buff, max_buff_line, 0); if (bytes < 0) {printf ("Recv err:"); return-1;} if (bytes = = 0) {fd_clr (SOCKFD, Global_rdfs), Close (SOCKFD);p rintf ("Recv:null data:"); return 0;} if (!strcmp (buff, "Q")) {//There is a custom small rule here, that is, when the Q is sent out, the connection fd_clr (SOCKFD, Global_rdfs); Close (SOCKFD);p rintf ("quit!\n"); return 0;} Buff[bytes] = ';p rintf ("%s\n", buff); Send (sockfd, buff, bytes, 0); return 0;} int Create_socket () {int listenfd, err;int len;struct sockaddr_in servaddr;int ret, opt = 1;LISTENFD = socket (Af_inet, SOCK _stream, 0); if (LISTENFD < 0) {printf ("Socket ERR:"); return-1;} Change LISTENFD to non-blocking if (ret = setsockopt (LISTENFD, Sol_socket, so_reuseaddr, &opt, sizeof (OPT))) < 0) {printf ("Error , set socket reuse addr Failed "); return-1;} Bzero (&servaddr, sizeof (SERVADDR)); Servaddr.sin_family = Af_inet;servaddr.sin_port = htons (port); servaddr.sin_addr.s_addr = htonl (inaddr_any); len = sizeof (struct SOCKADD r); err = bind (LISTENFD, (struct sockaddr *) &servaddr, Len); if (Err < 0) {printf ("Bind err:"); return-1;} Err = Listen (LISTENFD, Max_listen_que), if (Err < 0) {printf ("Listen err:"); return-1;} return LISTENFD;}
TCP IO multiplexing Select concurrency server-side Linux Socket Programming Primer (3)