socket network programming of liunx

Posted by GirishR on Fri, 04 Mar 2022 11:36:18 +0100

Socket network programming is a technology, which is often used in network communication. The biggest difference between socket and interprocess communication is that socket network programming is based on multi machine information transmission, while the former is based on single machine.

1, Understand the difference between TCP and UDP.

① TCP is connection oriented (for example, dial up to establish a connection before making a call; UDP is connectionless, that is, it is not necessary to establish a connection before sending data.
② TCP provides reliable services. In other words, the data transmitted through TCP connection is error free, not lost, not repeated, and arrives in sequence; UDP does its best to deliver, that is, reliable delivery is not guaranteed.
③ TCP is byte stream oriented. In fact, TCP regards data as a series of unstructured byte streams; UDP is a message oriented UDP without congestion control. Therefore, congestion in the network will not reduce the sending rate of the source host (very useful for real-time applications, such as IP telephony, real-time video conference, etc.).
④ Each TCP connection can only be point-to-point; UDP supports one-to-one, one to many, many to one and many to many interactive communication.
⑤ TCP header overhead 20 bytes; The overhead of UDP header is small, only 8 bytes.
⑥ The logical communication channel of TCP is a full duplex reliable channel, while UDP is an unreliable channel.

2, API for socket programming

1. Byte order conversion API

uint16_t htons(uint16_t host16bitvalue);    //Returns the value of the network byte order
uint32_t htonl(uint32_t host32bitvalue);    //Returns the value of the network byte order
uint16_t ntohs(uint16_t net16bitvalue);     //Returns the value of the host byte order
uint32_t ntohl(uint32_t net32bitvalue);     //Returns the value of the host byte order

h representative host,n representative net,s representative short(Two bytes), l representative long(4 Bytes), the conversion between host byte order and network byte order can be realized through the above four functions. Sometimes it can be used INADDR_ANY,INADDR_ANY Specify the address for the operating system to obtain

2. Address translation API

int inet_aton(const char * straddr,struct in_addr *addrp)
Description: put the string form"192.168.1.123"Convert to a format recognized by the network
 First parameter: IP The address of the string.
The second parameter: the address of the string

char *inet_ntoa(struct in_addr inaddr);
Network format ip Convert address to string form

3. Create communication endpoint socket

int socket(int domain, int type, int protocol);

The first parameter is:Specify a communication domain,Commonly used AF_INET(IPv4 Internet protocols)

The second parameter is:socket Type of formulation,Commonly used SOCK_STREAM(Provide orderly, reliable, bidirectional and connection based byte stream. It can be supported by out of band data transmission mechanism.)

The third parameter is:parameter protocol Used to indicate the protocol packet to be received,Usually write 0 to receive any IP Data packet. The verification and protocol analysis are completed by the program itself

Return value:If successful, the file descriptor of the new socket is returned. If failed, return-1. 

eg: socket(AF_INET,SOCK_STREAM,0);

4. Bind name to socket bind

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

The first parameter is:The file identifier returned when creating the communication endpoint.

The second parameter is:addr Pointer to structure variable,Here we use sockaddr_in Structure, and then cast to sockaddr Type.

sockaddr_in structural morphology
struct sockaddr_in{
	sa_family_t sin_family; //Address Family, i.e. address type
	uint16_t sin_port; //16 bit port number
	struct in_addr sin_addr; //32-bit IP address
	char sin_zero[8]; //Not used, usually filled with 0
};

The third parameter is:addrlen by addr The size of the variable can be determined by sizeof() Calculated.

Return value:If successful, 0 is returned. When an error occurs, return-1,And set errno Appropriate.

eg:bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

5. listen to the connection on the socket

int listen(int sockfd, int backlog);

The first parameter is:The file identifier returned when creating the communication endpoint.

The second parameter is:backlog Parameter defines the maximum length of the pending queue sockfd Connections may increase. If the queue is full when the connection request arrives, the client may receive an indication that ECONNRE‐If the underlying protocol supports retransmission, the request can be ignored in order to succeed when trying to connect again in the future.

Return value:If successful, 0 is returned. When an error occurs, return-1,And set errno Appropriate.

eg:listen(s_fd,10);

6. Receive connection on socket

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

The first parameter is:The file identifier returned when creating the communication endpoint.

The second parameter is: addr Is pointing sockaddr Pointer to structure, type conversion required. if it is NULL,be addrlen Also empty

The third parameter is: adr Address of length.

Return value:If successful, these system calls will return a nonnegative integer a The descriptor of the accepted socket. Error, return-1,errn For the appropriate settings.

eg: int adr=sizeof(struct sockaddr_in);
    a_fd=accept(s_fd,(struct sockaddr *)&a_addr,&adr);

7. Initiate a connection on the socket connect

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

The first parameter is the file identifier returned when creating the communication endpoint.

The second parameter is: addr Is the address to access.

The third parameter is: the length of the address to be accessed.

Return value: 0 if successful. When an error occurs, return-1,And set errno Appropriate.

3, Server side construction (two persons)

① Create communication endpoint socket
② Bind name to socket (IP address and port number)
③ Listening connection
④ Receive socket connection
⑤ Data interaction (read, send)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc,char **argv)
{
        int s_fd;
        int a_fd;
        int n_read;
        char readbuff[128];
        char msg[128]={0};
        struct sockaddr_in s_addr;
        struct sockaddr_in a_addr;
        
	if(argc!=3){
		printf("progrm is not good\n");
		exit(-1);
	}
	
	memset(&s_addr,0,sizeof(struct sockaddr_in));   //reset
        memset(&a_addr,0,sizeof(struct sockaddr_in));   //reset


        //1.socket
        s_fd=socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                perror("socket");
                exit(-1);
        }

        //2.bind
        s_addr.sin_family=AF_INET;
        s_addr.sin_port=htons(atoi(argv[2]));
        //s_addr.sin_addr.s_addr=("127.0.0.1");
        inet_aton(argv[1],&s_addr.sin_addr);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        //3.listen
        listen(s_fd,10);

        //4.accept
        int adr=sizeof(struct sockaddr_in);
	while(1){
        	a_fd=accept(s_fd,(struct sockaddr *)&a_addr,&adr);
        	if(a_fd==-1){
                	perror("accept");
        	}
        	printf("get connect:%s\n",inet_ntoa(a_addr.sin_addr));
        	
		if(fork()==0){
			if(fork()==0){
				while(1){
					//write
                        		memset(msg,0,sizeof(msg));
					printf("input: ");
					gets(msg);
					write(a_fd,msg,strlen(msg));
				}
			}
			//read
			while(1){
        			memset(readbuff,0,sizeof(readbuff));
				n_read=read(a_fd,readbuff,128);	
        			if(n_read==-1){
                			perror("read");
        			}else{
        				printf("get message from client:%d,%s\n",n_read,readbuff);
        		        }
			}
			break;	
		}
	}
        return 0;
}

4, Construction of receiving end (two persons)

① Create communication endpoint
② Initiate connection
③ Send data
④ Read data

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc,char **argv)
{
        int c_fd;
        int n_read;
        char readbuff[128];
        char msg[128]={0};
        struct sockaddr_in c_addr;
       
	if(argc!=3){
                printf("progrm is not good\n");
                exit(-1);
        }

	memset(&c_addr,0,sizeof(struct sockaddr_in));   //reset


        //1.socket
        c_fd=socket(AF_INET,SOCK_STREAM,0);
        if(c_fd == -1){
                perror("socket:\n");
                exit(-1);
        }

	 //2.connect
        c_addr.sin_family=AF_INET;
        c_addr.sin_port=htons(atoi(argv[2]));
        inet_aton(argv[1],&c_addr.sin_addr);

        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr))==-1){
                perror("connect\n");
                exit(-1);
        }
	while(1){
		if(fork()==0){
			while(1){
				memset(msg,0,sizeof(msg));
				printf("input: ");
				gets(msg);
				//3.write
       				write(c_fd,msg,strlen(msg));
			}
		}		
		while(1){	
		 	//3.read
			memset(readbuff,0,sizeof(readbuff));
       		 	n_read=read(c_fd,readbuff,128);
       		 	if(n_read==-1){
       				printf("perror:\n");
       		 	}else{
               	 		printf("I get message from server:%d,context:%s\n",n_read,readbuff);
       		 	}
		}
	}
        return 0;
}

For multi machine communication, only the server side needs to be modified
① Define mark to identify the number of client numbers
② Change accept

//4.accept
        int adr=sizeof(struct sockaddr_in);
        while(1){
                a_fd=accept(s_fd,(struct sockaddr *)&a_addr,&adr);
                if(a_fd==-1){
                        perror("accept");
                }
                mark++;
                printf("get connect:%s\n",inet_ntoa(a_addr.sin_addr));

                if(fork()==0){
                        if(fork()==0){
                                while(1){
                                        //write
                                        sprintf(msg,"Welcom No.%d client",mark); //Current client number
                                        write(a_fd,msg,strlen(msg));
                                        sleep(3);
                                }
                        }
                        //read
                        while(1){
                                memset(readbuff,0,sizeof(readbuff));
                                n_read=read(a_fd,readbuff,128);
                                if(n_read==-1){
                                        perror("read");
                                }else{
                                        printf("get message from client:%d,%s\n",n_read,readbuff);
                                }
                        }
                        break;
                }
        }

Topics: Linux