As a TCP Service Program At the same time, there may be a large number of clients connected, and we hope to remember each socket separately
Who has the data to read and put it in a request queue -- these tasks are completed by one thread and another result queue. If the result contains the socket number, use a thread to specifically:
Retrieve the original sender's socket by serial number and send it back to the original client. Another one is the processing thread (pool), which extracts a request from the request queue for processing,
I don't know if there is a ready-made framework to put the processing result into the result queue?
I can only find some great online... Of:
Http://fanqiang.chinaunix.net/a4/b7/20010508/112359.html
Linux Network Programming-9. Server Model
Http://linuxc.51.net Author: Hoyt (11:23:59) studied software engineering. software Engineering is a required course for every programmer. if you have never studied, we suggest you take a look. in this chapter, we will learn the idea of network programming from the perspective of software engineering. before writing programs, we should plan our software from the perspective of software engineering, so that we can develop software more efficiently. in network programs, many clients usually correspond to one server. in order to process client requests, special requirements are put forward for the server program. let's take a look at the most common server models. cyclic server: the cyclic server can only respond to requests from one client at the same time. Concurrent Server can respond to requests from multiple clients at the same time. 9.1 cyclic server: UDP Server
The implementation of UDP cyclic server is very simple: the UDP server reads a client request from the socket each time, processes the request, and returns the result to the client. You can use the following Algorithm To implement. socket (...);
BIND (...);
While (1)
{
Recvfrom (...);
Process (...);
Sendto (...);
} Because UDP is non-connection-oriented, no client can occupy the server. As long as the processing process is not an endless loop, the server will always be able to meet the requirements of each client.
9.2 cyclic server: TCP Server
The implementation of the TCP cyclic server is not difficult: the TCP Server accepts a client connection, processes it, completes all the requests of the client, and disconnects. the algorithm is as follows: socket (...);
BIND (...);
Listen (...);
While (1)
{
Accept (...);
While (1)
{
Read (...);
Process (...);
Write (...);
}
Close (...);
} The TCP cyclic server can only process requests from one client at a time. the server can continue the subsequent request only after all the requests of this customer are met. in this way, if a client occupies the server, other clients cannot work. therefore, the TCP server rarely uses the cyclic server model. 9.3 concurrent server: TCP Server
To make up for the defects of the cyclic TCP server, people have come up with a concurrent server model. the idea of a concurrent server is that the request of each client is not directly processed by the server, but is created by the server to process the request. the algorithm is as follows: socket (...);
BIND (...);
Listen (...);
While (1)
{
Accept (...);
If (Fork (..) = 0)
{
While (1)
{
Read (...);
Process (...);
Write (...);
}
Close (...);
Exit (...);
}
Close (...);
} The TCP concurrent server can solve the problem where the TCP cyclic Server Client excludes the server. however, it also brings a lot of problems. to respond to client requests, the server creates sub-processes to process the requests. creating a sub-process is a resource-consuming operation. 9.4 concurrent server: multiplexing I/O
In order to solve the system resource consumption caused by creating sub-processes, people come up with a multiplexing I/O model. First, we introduce a function selectint select (INT NFDs, fd_set * readfds, fd_set * writefds,
Fd_set * Records t FDS, struct timeval * timeout)
Void fd_set (int fd, fd_set * fdset)
Void fd_clr (int fd, fd_set * fdset)
Void fd_zero (fd_set * fdset)
Int fd_isset (int fd, fd_set * fdset) generally, when we read or write data to a file, the process may block reading and writing until certain conditions are met. for example, when we read data from a socket, there may be no data readable in the buffer (the communication peer has not sent the data). At this time, our read call will wait (blocking) until data is readable. if we do not want to block it, one of our options is to use the Select system call. as long as we have set the select parameters, when the file can be read and written, select back "notice" We say it can be read and written. set of file descriptors of all readfds files to be read
Writefds: Set of all file descriptors to be written. Required TFDs: timeout settings for file descriptors to be notified to us by other servers. NFDs all the largest plus 1 in the file descriptor we monitor will block the process until one of the following occurs when we call select. 1) files can be read. 2) files can be written. 3) the time specified for the timeout period is up. to set file descriptors, we need to use several macros. fd_set adds FD to fdsetfd_clr clears FD from fdset fd_zero clears all file descriptors from fdset fd_isset to determine whether FD uses the select example in the fdset set int use_select (int * readfd, int N)
{
Fd_set my_readfd;
Int maxfd;
Int I;
Maxfd = readfd [0];
For (I = 1; I if (readfd [I]> maxfd) maxfd = readfd [I];
While (1)
{
/* Add all file descriptors */
Fd_zero (& my_readfd );
For (I = 0; I fd_set (readfd [I], * my_readfd );
/* Process blocking */
Select (maxfd + 1, & my_readfd, null, null );
/* Something can be read */
For (I = 0; I if (fd_isset (readfd [I], & my_readfd ))
{
/* It turns out that I can read it */
We_read (readfd [I]);
}
}
} After Select is used, our server program becomes. initial statement (socket, bind, listen );
While (1)
{
Sets the listener's read/write file descriptor (FD _*);
Call select;
If the listener socket is ready, a new connection request is established.
{
Establish a connection (accept );
Add it to the listener file descriptor;
}
Otherwise, it indicates a descriptor that has been connected.
{
Read or write operations );
}
} Multiplexing I/O can solve resource restrictions. the UDP loop model is actually used on TCP. this brings about some problems. if the server processes client requests in sequence, some customers may wait for a long time. 9.5 concurrent server: UDP Server
People apply the concept of concurrency to UDP and get the concurrency UDP server model. the concurrent UDP server model is actually simple. like the concurrent TCP server model, the algorithm used to create a sub-process is the same as the concurrent TCP model. unless the server takes a long time to process client requests, this model is rarely used. 9.6 one concurrent TCP server instance # include
# Include
# Include
# Include
# Include
# Define my_port 8888int main (INT argc, char ** argv)
{
Int listen_fd, accept_fd;
Struct sockaddr_in client_addr;
Int N;
If (listen_fd = socket (af_inet, sock_stream, 0) <0)
{
Printf ("socket error: % s \ n \ A", strerror (errno ));
Exit (1 );
}
Bzero (& client_addr, sizeof (struct sockaddr_in ));
Client_addr.sin_family = af_inet;
Client_addr.sin_port = htons (my_port );
Client_addr.sin_addr.s_addr = htonl (inaddr_any );
N = 1;
/* If the server is terminated, the server can be started for the second time without waiting for a period of time */
Setsockopt (listen_fd, sol_socket, so_reuseaddr, & N, sizeof (INT ));
If (BIND (listen_fd, (struct sockaddr *) & client_addr, sizeof (client_addr) <0)
{
Printf ("BIND error: % s \ n \ A", strerror (errno ));
Exit (1 );
}
Listen (listen_fd, 5 );
While (1)
{
Accept_fd = accept (listen_fd, null, null );
If (accept_fd <0) & (errno = eintr ))
Continue;
Else if (accept_fd <0)
{
Printf ("Accept error: % s \ n \ A", strerror (errno ));
Continue;
}
If (n = fork () = 0)
{
/* The sub-process processes the client connection */
Char buffer [1024]; close (listen_fd );
N = read (accept_fd, buffer, 1024 );
Write (accept_fd, buffer, N );
Close (accept_fd );
Exit (0 );
}
Else if (n <0)
Printf ("fork error: % s \ n \ A", strerror (errno ));
Close (accept_fd );
}
} You can use the client program we wrote before to debug the program, or use Telnet for debugging.
---- Baidu cannot be big enoughArticleFor details, see the following address:
Http://blog.chinaunix.net/u2/63991/showart_509310.html