Source code for various TCP network servers in Linux

Source: Internet
Author: User
Tags htons

Everyone knows the compiling steps of various network server programs and knows that there are two types of network servers: cyclic services and concurrent services. Here is a summary of the source code.
First of all, the process of Loop Network Server programming is as follows: This type of server model is a typical Loop Service. Without the multi-process/thread technology, the Service throughput is limited. As you can see, if the data of the previous connection service is not sent and received, the subsequent Connections cannot be processed. Therefore, there is usually a multi-process technology that enables a new process to process a new connection, and the listening socket continues to listen.
************************ * ********************* Filename: realization of various types of TCP network server in Linux * purpose: record all kinds of tcp Service Program in Linux * wrote by: zhoulifa (zhoulifa@163.com) Zhou Lifa (http://zhoulifa.9999mb.com) linux enthusiasts Linux knowledge disseminators sohodevelopers are best at C Language * date time: 22:00:00 * Note: Anyone can copy code and use these documents at will, of course, it includes your commercial use * but follow GPL * Hope: I Hope more and more people will contribute their own strength, contribute to the development of science and technology *********************************** **********************************/
The source code of a loop TCP Service (because fork is used for multi-process services, this service is also useful in reality) as follows:

  1. /* ---------------------- Start of source code --------------------------------------------*/
  2. # Include <stdio. h>
  3. # Include <stdlib. h>
  4. # Include <errno. h>
  5. # Include <string. h>
  6. # Include <sys/types. h>
  7. # Include <netinet/in. h>
  8. # Include <sys/socket. h>
  9. # Include <sys/wait. h>
  10. /*************************************** ******************************
  11. * Filename: cycletcpserver. c
  12. * Purpose: a circular tcp server program
  13. * Tidied by: zhoulifa (zhoulifa@163.com) Zhou Lifa (http://zhoulifa.9999mb.com)
  14. Linux enthusiasts Linux knowledge disseminators sohowhose developers are best at C Language
  15. * Date time: 2006-07-04 22:00:00
  16. * Note: Anyone can copy the code and use these documents, including your commercial use.
  17. * But follow the GPL
  18. * Thanks to: Google.com
  19. **************************************** *****************************/
  20. Int main (int argc, char ** argv)
  21. {
  22. Int sockfd, new_fd;/* listen to socket: sock_fd, data transmission socket: new_fd */
  23. Struct sockaddr_in my_addr;/* local address information */
  24. Struct sockaddr_in their_addr;/* customer address information */
  25. Unsigned int sin_size, myport, lisnum;
  26. If (argv [1]) myport = atoi (argv [1]);
  27. Else myport = 7838;
  28. If (argv [2]) lisnum = atoi (argv [2]);
  29. Else lisnum = 2;
  30. If (sockfd = socket (PF_INET, SOCK_STREAM, 0) =-1 ){
  31. Perror ("socket ");
  32. Exit (1 );
  33. }
  34. My_addr.sin_family = PF_INET;
  35. My_addr.sin_port = htons (myport );
  36. My_addr.sin_addr.s_addr = INADDR_ANY;
  37. Bzero (& (my_addr.sin_zero), 0 );
  38. If (bind (sockfd, (struct sockaddr *) & my_addr, sizeof (struct sockaddr) =-1 ){
  39. Perror ("bind ");
  40. Exit (1 );
  41. }
  42. If (listen (sockfd, lisnum) =-1 ){
  43. Perror ("listen ");
  44. Exit (1 );
  45. }
  46. While (1 ){
  47. Sin_size = sizeof (struct sockaddr_in );
  48. If (new_fd = accept (sockfd, (struct sockaddr *) & their_addr, & sin_size) =-1 ){
  49. Perror ("accept ");
  50. Continue;
  51. }
  52. Printf ("server: got connection from % s \ n", inet_ntoa (their_addr.sin_addr ));
  53. If (! Fork () {/* child process code segment */
  54. If (send (new_fd, "Hello, world! \ N ", 14, 0) =-1 ){
  55. Perror ("send ");
  56. Close (new_fd );
  57. Exit (0 );
  58. }
  59. }
  60. Close (new_fd);/* the socket is no longer required by the parent process */
  61. Waitpid (-1, NULL, WNOHANG);/* wait until the child process ends and clear the resources occupied by the child process */
  62. }
  63. }
  64. /* ---------------------- Source code end --------------------------------------------*/

Copy code

The code for a test client is as follows:

  1. /* ---------------------- Start of source code --------------------------------------------*/
  2. # Include <stdio. h>
  3. # Include <stdlib. h>
  4. # Include <errno. h>
  5. # Include <string. h>
  6. # Include <netdb. h>
  7. # Include <sys/types. h>
  8. # Include <netinet/in. h>
  9. # Include <sys/socket. h>
  10. # Define MAXDATASIZE 100/* maximum data transmission volume each time */
  11. /*************************************** ******************************
  12. * Filename: cycletcpclient. c
  13. * Purpose: cyclic tcp client program
  14. * Tidied by: zhoulifa (zhoulifa@163.com) Zhou Lifa (http://zhoulifa.9999mb.com)
  15. Linux enthusiasts Linux knowledge disseminators sohowhose developers are best at C Language
  16. * Date time: 2006-07-04 22:20:00
  17. * Note: Anyone can copy the code and use these documents, including your commercial use.
  18. * But follow the GPL
  19. * Thanks to: Google.com
  20. * Hope: more and more people are expected to contribute to the development of science and technology.
  21. **************************************** *****************************/
  22. Int main (int argc, char * argv [])
  23. {
  24. Int sockfd, numbytes;
  25. Char buf [MAXDATASIZE];
  26. Struct hostent * he;
  27. Struct sockaddr_in their_addr;
  28. Unsigned int myport;
  29. If (argv [2]) myport = atoi (argv [2]);
  30. Else myport = 7838;
  31. If (argc! = 3 ){
  32. Fprintf (stderr, "usage: % s hostname port \ n", argv [0]);
  33. Exit (1 );
  34. }
  35. If (he = gethostbyname (argv [1]) = NULL ){
  36. Herror ("gethostbyname ");
  37. Exit (1 );
  38. }
  39. If (sockfd = socket (PF_INET, SOCK_STREAM, 0) =-1 ){
  40. Perror ("socket ");
  41. Exit (1 );
  42. }
  43. Their_addr.sin_family = PF_INET;
  44. Their_addr.sin_port = htons (myport );
  45. Their_addr.sin_addr = * (struct in_addr *) he-> h_addr );
  46. Bzero (& (their_addr.sin_zero), 0 );
  47. If (connect (sockfd, (struct sockaddr *) & their_addr, sizeof (struct sockaddr) =-1 ){
  48. Perror ("connect ");
  49. Exit (1 );
  50. }
  51. If (numbytes = recv (sockfd, buf, MAXDATASIZE, 0) =-1 ){
  52. Perror ("recv ");
  53. Exit (1 );
  54. }
  55. Buf [numbytes] = 0;
  56. Printf ("Received: % s \ n", buf );
  57. Close (sockfd );
  58. Return 0;
  59. }
  60. /* ---------------------- Source code end --------------------------------------------*/

Copy code

Use gcc cycletcpserver. c-o tcpserver and gcc cycletcpclient. c-o tcpclient to compile the above Code and the running status is as follows:

Administrator @ ubuzlf:/data/example/c $./tcpserver server: got connection from 127.0.0.1 server: got connection from 127.0.0.1 server: got connection from 127.0.0.1

Client running display:

Administrator @ ubuzlf:/data/example/c $./tcpclient 127.0.0.1 7838 stored ed: Hello, world!
Administrator @ ubuzlf:/data/example/c $./tcpclient 127.0.0.1 7838 stored ed: Hello, world!
Administrator @ ubuzlf:/data/example/c $./tcpclient 127.0.0.1 7838 stored ed: Hello, world!

I have to say a conceptual problem: blocking and non-blocking are in the blocking service. What happens when the server runs an accept statement without a Client Connecting to the service request? Then the server stops waiting for the connection service request on the accept statement. Similarly, when the program runs to receive the data statement recv, if no data can be read, the program will also stop on the receiving statement. This is called blocking ). However, if you want the server to check whether a client is waiting for a connection, you can accept the connection. Otherwise, you can continue to do other things by setting the socket to a non-blocking method: the non-blocking socket enables the accept call to return immediately when no client is waiting. By setting the socket as a non-blocking method, you can implement "polling" Several sockets. When an attempt is made to read data from a non-blocking socket without data waiting for processing, the function will return immediately, and the return value is set to-1, and errno is set to EWOULDBLOCK. However, this "Round Robin" will make the CPU in a busy waiting mode, thus reducing performance. Considering this situation, if you want the server to listen to Connection Service requests and read data from established connections, you may think of using one accept statement and multiple recv () statements, however, since both accept and recv are blocked, this idea is obviously not successful. Calling a non-blocking socket will greatly waste system resources. The call to select () can effectively solve this problem. It allows you to hook the process itself and enable the system kernel to listen to any activity of a set of file descriptors required by the system kernel, as long as the activity is confirmed on any monitored file descriptor, the select () call will return information indicating that the file descriptor is prepared, so as to select random changes for the process, the CPU overhead does not need to be wasted because the process itself tests the input.
Second, the concurrent server, in the above cycletcpserver. in c, fork technology can also be called a concurrent server, but this server is not a real I/O multiplexing concurrent server, and because it does not handle blocking problems, there are various problems in practical application.
A typical single-process concurrent server with IO multiplexing is as follows:/* IO multiplexing concurrent service flowchart */The following is a source program that demonstrates IO multiplexing and is a port forwarding program, however, it is very useful. In actual applications, all types of proxy software or port ing software are based on such code, such as Windows WinGate and WinProxy. The source code is as follows:

  1. /* ---------------------- Start of source code --------------------------------------------*/
  2. # Include <stdlib. h>
  3. # Include <stdio. h>
  4. # Include <unistd. h>
  5. # Include <sys/time. h>
  6. # Include <sys/types. h>
  7. # Include <string. h>
  8. # Include <signal. h>
  9. # Include <sys/socket. h>
  10. # Include <netinet/in. h>
  11. # Include <arpa/inet. h>
  12. # Include <errno. h>
  13. Static int forward_port;
  14. # Undef max
  15. # Define max (x, y) (x)> (y )? (X): (y ))
  16. /************************* About this document *********** *************************
  17. * Filename: tcpforwardport. c
  18. * Purpose: demonstrate the usage of select, which is an excellent agent software core and used for port ing.
  19. * Tidied by: zhoulifa (zhoulifa@163.com) Zhou Lifa (http://zhoulifa.9999mb.com)
  20. Linux enthusiasts Linux knowledge disseminators sohowhose developers are best at C Language
  21. * Date time: 2006-07-05 19:00:00
  22. * Note: Anyone can copy the code and use these documents, including your commercial use.
  23. * But follow the GPL
  24. * Thanks to: Paul Sheer Thanks to Paul Sheer for providing the source code in the select_tut man manual.
  25. * Hope: more and more people are expected to contribute to the development of science and technology.
  26. **************************************** *****************************/
  27. Static int listen_socket (int listen_port ){
  28. Struct sockaddr_in;
  29. Int s;
  30. Int yes;
  31. If (s = socket (AF_INET, SOCK_STREAM, 0) <0 ){
  32. Perror ("socket ");
  33. Return-1;
  34. }
  35. Yes = 1;
  36. If (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) & yes, sizeof (yes) <
  37. 0 ){
  38. Perror ("setsockopt ");
  39. Close (s );
  40. Return-1;
  41. }
  42. Memset (& a, 0, sizeof ());
  43. A. sin_port = htons (listen_port );
  44. A. sin_family = AF_INET;
  45. If (bind (s, (struct sockaddr *) & a, sizeof (a) <0 ){
  46. Perror ("bind ");
  47. Close (s );
  48. Return-1;
  49. }
  50. Printf ("accepting connections on port % d \ n", (int) listen_port );
  51. Listen (s, 10 );
  52. Return s;
  53. }
  54. Static int connect_socket (int connect_port, char * address ){
  55. Struct sockaddr_in;
  56. Int s;
  57. If (s = socket (AF_INET, SOCK_STREAM, 0) <0 ){
  58. Perror ("socket ");
  59. Close (s );
  60. Return-1;
  61. }
  62. Memset (& a, 0, sizeof ());
  63. A. sin_port = htons (connect_port );
  64. A. sin_family = AF_INET;
  65. If (! Inet_aton (address, (struct in_addr *) & a. sin_addr.s_addr )){
  66. Perror ("bad IP address format ");
  67. Close (s );
  68. Return-1;
  69. }
  70. If (connect (s, (struct sockaddr *) & a, sizeof (a) <0 ){
  71. Perror ("connect ()");
  72. Shutdown (s, SHUT_RDWR );
  73. Close (s );
  74. Return-1;
  75. }
  76. Return s;
  77. }
  78. # Define SHUT_FD1 {\
  79. If (fd1> = 0 ){\
  80. Shutdown (fd1, SHUT_RDWR );\
  81. Close (fd1 );\
  82. Fd1 =-1 ;\
  83. }\
  84. }
  85. # Define SHUT_FD2 {\
  86. If (fd2> = 0 ){\
  87. Shutdown (fd2, SHUT_RDWR );\
  88. Close (fd2 );\
  89. Fd2 =-1 ;\
  90. }\
  91. }
  92. # Define BUF_SIZE 1024
  93. Int main (int argc, char ** argv ){
  94. Int h;
  95. Int fd1 =-1, fd2 =-1;
  96. Char buf1 [BUF_SIZE], buf2 [BUF_SIZE];
  97. Int buf1_avail, buf1_written;
  98. Int buf2_avail, buf2_written;
  99. If (argc! = 4 ){
  100. Fprintf (stderr, "Usage \ n \ tfwd \ n ");
  101. Exit (1 );
  102. }
  103. Signal (SIGPIPE, SIG_IGN );
  104. Forward_port = atoi (argv [2]);
  105. /* Create a listener socket */
  106. H = listen_socket (atoi (argv [1]);
  107. If (h <0) exit (1 );
  108. For (;;){
  109. Int r, nfds = 0;
  110. Fd_set rd, wr, er;
  111. FD_ZERO (& rd );
  112. FD_ZERO (& wr );
  113. FD_ZERO (& er );
  114. FD_SET (h, & rd );
  115. /* Put the listening socket and the readable socket together into the select readable handle list */
  116. Nfds = max (nfds, h );
  117. If (fd1> 0 & buf1_avail <BUF_SIZE ){
  118. FD_SET (fd1, & rd );
  119. Nfds = max (nfds, fd1 );
  120. }
  121. If (fd2> 0 & buf2_avail <BUF_SIZE ){
  122. FD_SET (fd2, & rd );
  123. Nfds = max (nfds, fd2 );
  124. }
  125. /* Put the writeable socket two together into the select writable handle list */
  126. If (fd1> 0 & buf2_avail-buf2_written> 0 ){
  127. FD_SET (fd1, & wr );
  128. Nfds = max (nfds, fd1 );
  129. }
  130. If (fd2> 0 & buf1_avail-buf1_written> 0 ){
  131. FD_SET (fd2, & wr );
  132. Nfds = max (nfds, fd2 );
  133. }
  134. /* Put the two sockets with abnormal data into the select exception handle list */
  135. If (fd1> 0 ){
  136. FD_SET (fd1, & er );
  137. Nfds = max (nfds, fd1 );
  138. }
  139. If (fd2> 0 ){
  140. FD_SET (fd2, & er );
  141. Nfds = max (nfds, fd2 );
  142. }
  143. /* Start select */
  144. R = select (nfds + 1, & rd, & wr, & er, NULL );
  145. If (r =-1 & errno = EINTR) continue;
  146. If (r <0 ){
  147. Perror ("select ()");
  148. Exit (1 );
  149. }
  150. /* Process new connections */
  151. If (FD_ISSET (h, & rd )){
  152. Unsigned int l;
  153. Struct sockaddr_in client_address;
  154. Memset (& client_address, 0, l = sizeof (client_address ));
  155. R = accept (h, (struct sockaddr *) & client_address, & l );
  156. If (r <0 ){
  157. Perror ("accept ()");
  158. } Else {
  159. /* Close the original connection, use the new connection as fd1, and connect to the new target fd2 */
  160. SHUT_FD1;
  161. SHUT_FD2;
  162. Buf1_avail = buf1_written = 0;
  163. Buf2_avail = buf2_written = 0;
  164. Fd1 = r;
  165. Fd2 = connect_socket (forward_port, argv [3]);
  166. If (fd2 <0 ){
  167. SHUT_FD1;
  168. } Else
  169. Printf ("connect from % s \ n", inet_ntoa (client_address.sin_addr ));
  170. }
  171. }
  172. /* NB: read oob data before normal reads */
  173. If (fd1> 0)
  174. If (FD_ISSET (fd1, & er )){
  175. Char c;
  176. Errno = 0;
  177. R = recv (fd1, & c, 1, MSG_OOB );
  178. If (r <1 ){
  179. SHUT_FD1;
  180. } Else
  181. Send (fd2, & c, 1, MSG_OOB );
  182. }
  183. If (fd2> 0)
  184. If (FD_ISSET (fd2, & er )){
  185. Char c;
  186. Errno = 0;
  187. R = recv (fd2, & c, 1, MSG_OOB );
  188. If (r <1 ){
  189. SHUT_FD1;
  190. } Else
  191. Send (fd1, & c, 1, MSG_OOB );
  192. }
  193. /* NB: read data from fd1 */
  194. If (fd1> 0)
  195. If (FD_ISSET (fd1, & rd )){
  196. R = read (fd1, buf1 + buf1_avail, BUF_SIZE-buf1_avail );
  197. If (r <1 ){
  198. SHUT_FD1;
  199. } Else
  200. Buf1_avail + = r;
  201. }
  202. /* NB: read data from fd2 */
  203. If (fd2> 0)
  204. If (FD_ISSET (fd2, & rd )){
  205. R = read (fd2, buf2 + buf2_avail, BUF_SIZE-buf2_avail );
  206. If (r <1 ){
  207. SHUT_FD2;
  208. } Else
  209. Buf2_avail + = r;
  210. }
  211. /* NB: write data to fd1 */
  212. If (fd1> 0)
  213. If (FD_ISSET (fd1, & wr )){
  214. R = write (fd1, buf2 + buf2_written, buf2_avail-buf2_written );
  215. If (r <1 ){
  216. SHUT_FD1;
  217. } Else
  218. Buf2_written + = r;
  219. }
  220. /* NB: write data to fd1 */
  221. If (fd2> 0)
  222. If (FD_ISSET (fd2, & wr )){
  223. R = write (fd2, buf1 + buf1_written, buf1_avail-buf1_written );
  224. If (r <1 ){
  225. SHUT_FD2;
  226. } Else
  227. Buf1_written + = r;
  228. }
  229. /* Check if write data has caught read data */
  230. If (buf1_written = buf1_avail) buf1_written = buf1_avail = 0;
  231. If (buf2_written = buf2_avail) buf2_written = buf2_avail = 0;
  232. /* One side has closed the connection, keep writing to the other side until empty */
  233. If (fd1 <0 & buf1_avail-buf1_written = 0 ){
  234. SHUT_FD2;
  235. }
  236. If (fd2 <0 & buf2_avail-buf2_written = 0 ){
  237. SHUT_FD1;
  238. }
  239. }
  240. Return 0;
  241. }
  242. /* ---------------------- Source code end --------------------------------------------*/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.