Network programming (API)

Keywords: TCP/IP

Network programming (API)

1, tcp

1. Server side

1) Create socket

	int socket(int domain, int type, int protocol);
 		parameter:
 			  domain:protocol family,AF_INET
         	  type:Communication type,tcp The agreement is SOCK_STREAM
              protocal:Specific agreement,Generally 0, default protocol
              Return value: File descriptor


2) Bind the file descriptor returned by the socket to the local address and port

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
	Parameters:
		sockfd: socket Returned file descriptor
		addr: Address structure pointer, storage ip Address and port number
		addrlen  Length of address structure
		Return value 0
	Note: the address structure is:
		struct sockaddr 
		{
			sa_family_t sa_family;      //Address protocol family
			char sa_data[14];           //Address port number
		}
	This is written to apply to various protocols, but 32-bit binary cannot be used IP Address and short integer
	The port number of type data is stored in a character array, so another structure is used
	Replace it:
		struct sockaddr_in
		{
         	__SOCKADDR_COMMON (sin_family);    //Address protocol family
        	in_port_t sin_port;                //Port number, 2byte
       	    struct in_addr sin_addr;          //IPV4 address
       	};  
	Note: the structure is in/usr/include/netinet/in.h Has been defined,
		Header file is<netinet/in.h> ;


Note: htons converts the port number from host byte order to network byte order (big end); inet_pton press the IP address AF_INET protocol family is converted into network address structure and stored in the third parameter.

3) Listen socket: listen to whether a client initiates a connection request

	int listen(int sockfd, int backlog);
     	parameter  sockfd  File descriptor
              backlog Number of waiting queue elements
            When the client initiates a connection to the server, the listening descriptor of the server is received on the port
            After the connection request of the client, the connection is not established immediately, but the request is placed on the server first
            In the queue to be, and then take out the requests from the queue in order to establish a connection.
    	A return value of 0 indicates success


4) Receive tcp connection: the server receives the request and establishes a connection

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
	Parameters: sockfd: File descriptor for listening
		  Addr: The input parameter is the address structure of the connected client
          addrlen   Length pointer of address structure
    Return value: file descriptor the descriptor used for communication


5) IO: use read/write or recv/send

6) close socket (file descriptor)

2. Client

1) socket: used for communication
2) connect: initiate connection actively

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
	Parameters: sockfd  Communication descriptor
     	  addr  Pointer to the address structure of the target server
          addrlen   Length of address structure
	Return value: success or failure 0/Not 0

3 ) IO

2, udp

1 System call used
	ssize_t sendto(int socket, void *message, size_t length, 
						int flags, struct sockaddr *dest_addr,
						socklen_t dest_len);
			
	ssize_t recvfrom(int socket, void *buffer, size_t length,
						 int flags, struct sockaddr *address,
						  socklen_t *address_len);
	Note: this function blocks when no data is received
	
	1) Server
		recvfrom
			socket	Listener descriptor
			buffer	Accepted data buf
			length	buf size
			flags	0
			address	When recvfrom When receiving data, save the client address information, sendto Use this structure when
			address_len	sockaddr Structure size
			
		sendto
			socket 	Listener descriptor
			message Data sent buf
			length  Send data size
			flags 0
			dest_addr client scokaddr_in Structure, recvfrom Filled structure
			dest_len	sockaddr Structure size
	2) client
		sendto
			socket 		descriptor 
			message 	Data sent buf
			length  	Send data size
			flags 0
			dest_addr 	Server scokaddr_in Structure, fill in the server address, port and other information
			dest_len	sockaddr Structure size
		
		recvfrom
			socket		descriptor 
			buffer		Accepted data buf
			length		buf size
			flags		0
			address		Server scokaddr_in Structure that receives data from the server   NULL
			address_len	sockaddr Structure size    NULL

Question: when the server communicates with the client, recv/send, read/write and recvfrom/sendto are blocking functions. If one client is connected and keeps opening, other clients will not be connected? Solving this problem requires server concurrency;

3, Concurrent server model

1. Multi process model: fock a child process for each connected client to perform I/O, but this will waste resources and is not recommended.

Code Description: if a client connects, it is its fork sub process. If it fails, close the file descriptor for communication and reconnect.

Code Description: if successful, I/O is performed in the child process

characteristic:
① fork is expensive. When forking, you need to copy all the resources of the parent process, including memory images;
② After fork ing child processes, the communication between parent-child processes and brother processes needs IPC mechanism, which brings difficulties to the communication;
③ Multi process still can't make effective use of system resources to a certain extent;
④ The number of processes in the system is also limited

2. Multithreading model: create a sub thread for each connected client for I/O, which will not consume so many resources. However, if there are common global variables, it is necessary to complete the mutual exclusion or synchronization of multithreads, which will be very complex.
Code Description: the communication descriptor needs to be passed into the sub thread for I/O, but before that, there may be a new client to connect, and the iClient will change, affecting the sub thread. Therefore, put the iClient in the heap application space to avoid this problem.

Code Description: create a thread. The following are thread functions:

3.I/O multiplexing model: call the function to create a table for monitoring the status of file descriptors, and then rotate all elements in the table. When a descriptor has a real IO request, the function returns to judge which file descriptor has an IO request, and then perform IO operations on the file descriptor. Then restore the table to its original state and continue monitoring

Function prototype:
int select(int nfds, fd_set *readfds, fd_set *writefds,
				fd_set *exceptfds, struct timeval *timeout);
Parameters: nfds  Maximum file descriptor+1  To monitor all file descriptors
      readfds   Read the address of the file descriptor set. This set mainly stores the file descriptor, which may cause read operations
      writefds  Write file descriptor set address
      exceptfds  Exception file descriptor collection address
      timeout   Time overflow  
				NULL: Blocks until a file descriptor is ready or an error occurs
				The time value is 0: only the state of the file descriptor set is detected, and then it is returned immediately
				The time value is not 0: if no event occurs within the specified time, the timeout will be returned.

Return value:>0  Really have IO Number of file descriptors for the operation
        =0  Time overflow but no IO
        <0  error
        
doubt: select I don't know which descriptor state in the monitoring has changed, and how to find that descriptor?
	 void FD_ZERO(fd_set *fdset)  Clear descriptor set
	 void FD_SET(int fd,fd_set *fdset) Add descriptor to collection 
	 void FD_CLR(int fd,fd_set *fdset) Clear descriptor from collection 
	 int FD_ISSET(int fd,fd_set *fdset)  Determine whether the descriptor is in the collection

Note: the kernel allows the select function to monitor up to 1024 descriptors:

advantage:

  1. Avoid the resources and time spent creating multiple threads.
  2. The polling of socket is completed in kernel mode, which does not need to switch like multithreading and consumes resources.
    The implementation of epoll can ensure that the performance is almost not affected by the number of connections (only connections and no other operations).

Posted by dzoddi on Sat, 20 Nov 2021 07:19:19 -0800