. Linux Network Programming --9 server model http://linuxc.51.net Author: hoyt
(2001-05-08 11:23:59)
Learn "Software Engineering". Software Engineering can be the course for each programmer "compulsory". If you have not learned, I suggest you go to see. In this chapter, we will come together from the perspective of software engineering. The idea of network programming. Before we write the program, we should plan our software from the perspective of software engineering, so that we have the efficiency of our development software. In the network program, generally many client corresponds to many clients A server. In order to deal with the client's request, a special requirement for the server is put forward. We learn the most common server model currently. Cycle server: The loop server can only respond to a client request concurrent server at the same time: The concurrent server can respond to the request 9.1 cycle server in the same time 9.1 loop server: UDP server UDP loop server is very simple: UDP server reads a client request, process, and then return the result back Client. You can use the following algorithm. Socket (...); bind (...); while (1) {recvfrom (...); process (...); sendto (...) Because UDP is non-connected, no client can always occupate the server. As long as the process is not a dead loop, the server can always meet each client. 9.2 Cycle Server: TCP Server TCP Cycle Server Implementation is not difficult: The TCP server accepts a client connection, then processes, after completing all the requests for this customer, disconnect. The algorithm is as follows: socket (...); bind (...); listen. ..); while (1) {accept (...); while (1) {read (...); process (...); write;} close (...); } The TCP loop server can only handle a client's request at a time. Only after all the requests in this customer are met, the server Can continue later. This way if there is a client to occupy the server, other clients can not work. Therefore, TCP servers generally use a loop server model. 9.3 Concurrent Server: TCP Server To make up Cyclic TCP server's defects, people think of the model of concurrent servers. The idea of concurrent servers is that each client's request is not directly handled by the server, but the server creates a child process. The algorithm is as follows: socket (.. .); Bind (...); while (1) {accept (...); if (fork (..) == 0) {while (1) {read (.. .);} Close (...); exit (...);} close (...);
} The TCP concurrent server can solve the situation of the TCP loop server client exclusively. However, it also brought a small problem. In response to the request of the client, the server wants to create a child process. And the creation sub-process is a kind of Very consumable resource operation. 9.4 Concurrent Server: Multi-channel Reuse I / O In order to solve system resource consumption caused by the creation sub-process, people want to have multiple reputation I / O models. First introduce a function Select int SELECT (int nfds, fd_set * readfds, fd_set * writefds, fd_set * except 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 and write to the file, the process may be blocked in the read and write until a certain condition is satisfied. For example, when we read the data from a socket, it is possible to buffer There is no data readable (the other party of communication has not sent data), this time our read call will wait until there is data readable. If we don't want to block, our choice is to call with the SELECT system. As long as we set the various parameters of SELECT, then when the file can be read and written, SELECT back "Notice" We said that you can read and write. Readfds All the file file descriptor for the file descriptor to read Writefds All to write file file descriptors Collecting ExcePTFDS Other Documents Timeout Timeout Timeout to We Notify us. NFDS All our most monitoring file descriptors 1 Add 1 When we call SELECT, the process will occur until one of the following situations. 1 Document can be read .2) There is a file can be written. 3) timeout set. To set up file descriptors We want to use several macros. FD_SET Add FD to fdset fd_clr to clear FD_zero from FDSET from fdset Clear all file descriptors fd_isset determine if the FD uses Select's example INT USE_SELECT (INT * READFD, INT N) {fd_set my_readfd; int maxfd; INT i; maxfd = readfd [0]; for (i = 1; IIF (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 Block * /
SELECT (MAXFD 1, & MY_READFD, NULL, NULL, NULL);
/ * There is something you can read * /
For (i = 0; i
IF (fd_isset (readfd [i], & my_readfd))
{
/ * It turned out that I can read it * /
WE_READ (ReadFD [i]);
}
}
}
Our server program turned after using SELECT.
First measuring (socket, bind, listen);
While (1)
{
Set the monitor read and write file descriptor (FD_ *);
Calling SELECT;
If you are listening to the socket ready, a new connection request is established.
{
Establish a connection (ACCEPT);
Add to the listening file descriptor;
}
Otherwise, it is a descriptor that has been connected.
{
Operation (READ or WRITE);
}
}
Multi-purpose I / O can solve resource restrictions. The model is actually used to use the UDP loop model on TCP. This also brought some questions. If the server sequentially handles the customer's request, it may Some customers will wait for a long time.
9.5 Concurrent Server: UDP Server
People have used concurrent concepts for UDP to get concurrent UDP server models. The concurrent UDP server model is actually simple. The same is the same as the concurrent TCP server model to create a child process to process the algorithm and the concurrent TCP model. Unless the server This model is actually rarely used in the process of processing the client's request.
9.6 A concurrent TCP server instance
#include
#include
#include
#include
#include
#define my_port 8888
INT 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 start quickly without waiting for a period of time * /
Setsockopt (Listen_FD, SOL_Socket, So_reuseAddr, & n, Sizeof (int));
IF (Bind (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)
{
/ * Sub process processing 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 write the client program to debug the program with our client program, or use Telnet debugging
(
http://www.fanqiang.com)