Linux Network Programming--tcp Server

Keywords: socket Mobile Programming network

First, what are the requirements for being a TCP server?

1. Having a known address (bind(): the equivalent of knowing the number of mobile customer service clearly before we can call them;

2. Let the operating system know that it is a server, not a client (listen()): equivalent to mobile customer service, their main responsibility is to passively answer user calls, rather than actively call to harass users;

3. Waiting for the arrival of the connection (accept(): Mobile customer service is always waiting for a customer to answer one.


The receiver uses bind() function to complete the binding of address structure and socket socket socket, so that IP and port are fixed, and the sender can send data to a specific address (ip+port). ) Receiver.

For TCP server programming process, it is somewhat similar to the process of answering a phone:

1. Find a cell phone to talk to (socket()

2. Insert a telephone card to fix a number (bind())

3. Responsibility for passive answering. Set up a ring tone to listen for incoming calls.

4. When there is an incoming call and the relationship between the two parties is confirmed, the acceptance () call is actually put through.

5. Receive the other party's complaint (recv()

6. Respond appropriately (send()

7. After the communication, both sides said goodbye and hung up.



int bind( int sockfd, const struct sockaddr *myaddr,socklen_t addrlen );
Functions:
Bind the local protocol address to sockfd so that ip and port are fixed Parameters:
sockfd: socket socket myaddr: Address structure pointer to a specific protocol addrlen: The length of the address structure Return value:
Success: Return to 0

Failure: -1

Note: bind can only bind its own address and port

Use examples:

  1. //Setting the local address structure  
  2.     struct sockaddr_in my_addr;  
  3.     bzero(&my_addr, sizeof(my_addr));           //Clean up and make sure the last 8 bytes are 0.  
  4.     my_addr.sin_family = AF_INET;               // ipv4  
  5.     my_addr.sin_port   = htons(port);           //Port  
  6.     my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//ip, INADDR_ANY is a wildcard address with a value of 0  
  7.       
  8.     //Binding  
  9.     int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
  10.     if( err_log != 0)  
  11.     {  
  12.         perror("binding");  
  13.         close(sockfd);        
  14.         exit(-1);  
  15.     }  

int listen(int sockfd, int backlog);
Functions:

Change socket from active to passive operating system Set up a connection queue for the socket to record all connections to the socket. For more details, see The relationship among connect(), listen() and accept()>.

Parameters:

sockfd: socket listening socket

backlog: length of connection queue

Return value:

Success: Return to 0

Failure: Others



int accept(  int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen );
Functions:

Remove an established connection from the connected queue and go to sleep waiting (blocking) if no connection is available. For more details, see< The relationship among connect(), listen() and accept()>.

Parameters:

sockfd: socket listening socket

cliaddr: Used to store client socket address structure

addrlen: Address of the length of the socket address structure

Return value:

Success: Connected socket. Note: The returned socket is a connected socket, which represents the current connection.

Failure: < 0


tcp_server code:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>                         
  4. #include <unistd.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>                  
  8. int main(int argc, char *argv[])  
  9. {  
  10.     unsigned short port = 8000; //Local ports  
  11.     if(argc > 1)                       
  12.     {  
  13.         port = atoi(argv[1]);  
  14.     }  
  15.     //1. Creating communication endpoints: sockets  
  16.     int sockfd = socket(AF_INET, SOCK_STREAM, 0);     
  17.     if(sockfd < 0)  
  18.     {  
  19.         perror("socket");  
  20.         exit(-1);  
  21.     }  
  22.       
  23.     //Setting Local Address Structure  
  24.     struct sockaddr_in my_addr;  
  25.     bzero(&my_addr, sizeof(my_addr));           //Clean up and make sure the last 8 bytes are 0.  
  26.     my_addr.sin_family = AF_INET;               // ipv4  
  27.     my_addr.sin_port   = htons(port);           //Port  
  28.     my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//ip, INADDR_ANY is a wildcard address with a value of 0  
  29.       
  30.     //2. Binding: Associating local ip, port and socket  
  31.     int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
  32.     if( err_log != 0)  
  33.     {  
  34.         perror("binding");  
  35.         close(sockfd);        
  36.         exit(-1);  
  37.     }  
  38.       
  39.     //3. Listen, listen socket changed to passive, create connection queue  
  40.     err_log = listen(sockfd, 10);   
  41.     if(err_log != 0)  
  42.     {  
  43.         perror("listen");  
  44.         close(sockfd);        
  45.         exit(-1);  
  46.     }     
  47.       
  48.     printf("listen client @port=%d...\n",port);  
  49.   
  50.     while(1)  
  51.     {     
  52.       
  53.         struct sockaddr_in client_addr;          
  54.         char cli_ip[INET_ADDRSTRLEN] = "";       
  55.         socklen_t cliaddr_len = sizeof(client_addr);      
  56.           
  57.         int connfd = 0;  
  58.           
  59.         //4. Extracting Client Connections from the Completion Connection Queue  
  60.         connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);         
  61.         if(connfd < 0)  
  62.         {  
  63.             perror("accept");  
  64.             continue;  
  65.         }  
  66.   
  67.         inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
  68.         printf("----------------------------------------------\n");  
  69.         printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));  
  70.           
  71.         char recv_buf[512] = "";  
  72.         while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) //Receiving data  
  73.         {  
  74.             printf("\nrecv data:\n");  
  75.             printf("%s\n",recv_buf);  
  76.         }  
  77.           
  78.         close(connfd);     //Close Connected Sockets  
  79.         printf("client closed!\n");  
  80.     }  
  81.       
  82.     close(sockfd);         //Close listening socket  
  83.       
  84.     return 0;  
  85. }  


Uses the network debugging assistant of windows as the client, and the above code is the server.
Operation results:



Close the connection: close()

The socket can be closed by using the close() function. Closing a socket representing a connected socket will cause the other end to receive a 0-length packet. For details, please see< TCP Waves Four Times.


Server

  • Closing listening sockets (sockets after socket() and listen() will cause the server to fail to receive new connections, but will not affect the established connections;
  • Closing the connected socket returned by accept() will cause the connection it represents to be closed, but will not affect the socket after the server listens (socket() and listen().


When doing client

Closing a connection means closing a connection, not something else.


If the connection between client and server is successful, usually, the client is shut down first, then the server is shut down. If the server is shut down first, the server is started immediately. The port bound by the server will not be released immediately (as shown below). It takes about a minute to release. Why? See "TCP Four Waves" . Is there a way to make the server succeed every time it starts? See Port Multiplexing.




Source download:


Posted by khaine on Sun, 21 Apr 2019 13:06:34 -0700