linux network communication

Posted by cosminb on Sat, 05 Mar 2022 15:32:41 +0100

linux network programming

1, socket

1. Detailed explanation of common functions

1.establish socket: 
	int socket(int domain, int type, int protocol); 
		domain: AF_INET This is most used to generate socket Protocol, use TCP or UDP To transmit, use IPv4 Address of
			 	AF_INET6 Similar to the above, but for use IPv6 Address of
	   		    AF_UNIX Local agreement
		type:SOCK_STREAM This protocol is a sequential, reliable and data complete connection based on byte stream. This is one of the most used socket Type, this socket Is to use TCP For transmission. 
				SOCK_DGRAM This protocol is a connectionless, fixed length transmission call. The protocol is unreliable to use UDP To connect it
		protocol: Passing 0 means using the default protocol.	protcol Is 0, according to type Select the appropriate protocol.		
		                When type yes sock_stream Time. protoc yes tcp
						When type yes sock_dgram Time.protcol yes udp
		Success: returns a pointer to the newly created socket File descriptor, failed: Return-1,set up errno	
		
	2.binding socket Ports and ip	
		Int bind(int sockfd,const struct sockaddr*addr,socklen_t addrlen);
			sockfd: Socket fd(File descriptor), socket()Return value of function
			addr: structural morphology ip+port(Port)
				struct sockaddr_in{ (Involving coercion sockaddr_in ->sockaddr  (Reference)
					short int sin_family;              //Address family
					unsigned short int sin_port;       //Port number
					struct in_addr sin_addr;           //IP address
				}
				struct in_addr {
				     __be32 s_addr;
				};
	3.set up sockefd Maximum number of simultaneous links			
	int listen(int sockfd,int backlog);
		backlog: Maximum number of requests to link client queues
		Return value: judge success or failure
		
	4.Wait for a sockfd Client response for
		int accept(int sockfd,struct sockaddr*addr,socklen_t*addrlen)
			addr: Outgoing parameters: the structure of the client to which I am connected (including the client) ip+Port)
			Return value: the socket connecting the client.
			When there is one client response listenfd When, accept Will return a connfd Communicate with clients.
	5.client And server signal communication
		int connect(int sockfd,struct sockaddr*serv_addr,int addrlen)
			sockfd: Pass in parameters and file descriptors to bind the server socket with successful connection, so as to facilitate the connection to the server at the client IO operation
			serv_addr: Bind the structure of the server I want to link (need to initialize binding) ip And fracture), indicating the purpose



2. Server code

Idea: use socket to create a listenfd, bind its server ip and port, set its maximum communication number, accept blocks listening, and when there is a client response, accept returns a connfd to communicate with the client. Listenfd is always used as the swap in parameter of accept to listen to the client. Whenever a client passes through it, a new connfd tone communication is set. It is equivalent to that connfd is the fd that binds the client ip and port. The server can communicate with connfd only by reading and writing connfd.

Single process server
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define SER_PORT 8000
int main(void)
{
	int sockfd,connfd;//
	int len;
	char wbuf[1024];
	char rbuf[1024];
	struct sockaddr_in serveraddr,clientaddr; //Two structures: one is used to bind the identity to the socket, and the other is used to receive the structure of the customer service end
	//1. Create a listening socket
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	//2.bind (socket is required for communication to bind the home address and house number to ip and port)
	bzero(&serveraddr,sizeof(serveraddr)); //Similar to memset emptying structure
	//Address family protocol, select IPV4
	serveraddr.sin_family = AF_INET;     //Is it ipv4 or ipv6
	//IP address any available IP address of the machine
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serveraddr.sin_port = htons(SER_PORT);//Port number	
	bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	//3. Sum of listening and server connection
	listen(sockfd,128);	
	int size = sizeof(clientaddr);
	//4.accept blocks the request to listen to the customer service link
	connfd = accept(sockfd,(struct sockaddr *)&clientaddr,&size); 	
	//Output ip and port of customer service terminal
	char ipstr[128];
	printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)),
		ntohs(clientaddr.sin_port));
	//5. Processing client requests
	//Reading and writing
	while(1)
	{
		memset(wbuf,0,sizeof(wbuf));//empty
		memset(rbuf,0,sizeof(wbuf));	
		//receive messages	
		int len = read(connfd,rbuf,sizeof(rbuf));
		if(len==0)//Indicates disconnection
		{
			printf("client is close....\n");
		}
		printf("receive from client:%s",rbuf);
		//send message
		printf("send to client:");
		fgets(wbuf,sizeof(wbuf),stdin);
		write(connfd,wbuf,strlen(wbuf));	
	}
	close(connfd);
	close(sockfd);
	return 0;
}

Multi process server
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <unistd.h>

#include "wrap.h"

#define MAXLINE 8192
#define SERV_PORT 8000

void do_sigchild(int num)
{
    while (waitpid(0, NULL, WNOHANG) > 0)
        ;
}

int main(void)
{
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int listenfd, connfd;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int i, n;
    pid_t pid;
    struct sigaction newact;

    newact.sa_handler = do_sigchild;
    sigemptyset(&newact.sa_mask);
    newact.sa_flags = 0;
    sigaction(SIGCHLD, &newact, NULL);

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    int opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    Listen(listenfd, 20);

    printf("Accepting connections ...\n");
    while (1) {
        cliaddr_len = sizeof(cliaddr);
        connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
        printf("-------------------------%d\n", connfd);

        pid = fork();
        if (pid == 0) {
            Close(listenfd);
            while (1) {
                n = Read(connfd, buf, MAXLINE);
                if (n == 0) {
                    printf("the other side has been closed.\n");
                    break;
                }
                printf("received from %s at PORT %d\n",
                        inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                        ntohs(cliaddr.sin_port));

                for (i = 0; i < n; i++)
                    buf[i] = toupper(buf[i]);

                Write(STDOUT_FILENO, buf, n);
                Write(connfd, buf, n);
            }
            Close(connfd);
            return 0;
        } else if (pid > 0) {
            Close(connfd);
        }  else
            perr_exit("fork");
    }
    return 0;
}



3. Client code

Code idea: create connfd and call connect to communicate with the ip and port of the server. It is worth noting that connfd can be bound to the ip and port of the client without using bind. It will be bound automatically when calling connect.

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define SER_PORT 8000
int main(void)
{
	int sockfd;
	struct sockaddr_in serveraddr;
	int len;
	char wbuf[1024],rbuf[1024];
	//1. Socket communication socket, create a sockfd
	sockfd = socket(AF_INET,SOCK_STREAM,0);
    char ipstr[]="127.0.0.1";
	//2. Edit the server address to which you want to connect and bind
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;            //Set address family protocol
	serveraddr.sin_port = htons(SER_PORT);      //Set port number
	inet_pton(AF_INET,ipstr,&serveraddr.sin_addr.s_addr);//Set the ip address point division decimal to network byte order
	//2. connect server sockfd outgoing server socket
	connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
	//3. Reading and writing
	while(1)
	{
		memset(wbuf,0,sizeof(wbuf));
		memset(rbuf,0,sizeof(rbuf));
		//send message
		printf("send to server:");
		fgets(wbuf,sizeof(wbuf),stdin);
		write(sockfd,wbuf,strlen(wbuf));
		
		//receive messages
		len=read(sockfd,rbuf,sizeof(rbuf));
		if(len==0)//Indicates disconnection
		{
			printf("server is close....\n");
		}
		printf("receive from server:%s",rbuf);
		
		
	}
	//4,close
	close(sockfd);
	return 0;
}

2, select

1. Concept of IO multiplexing

In the socket model, we block listening fd to block the process in accept. IO reuse means that the non blocking loop listens to connfd and listenfd in the server. When fd is ready and the process runs to the non blocking loop listening function, it will run the response program.
Multiplexing IO is to use one thread to listen to multiple IO requests at the same time and return when there are IO requests. Note that although our IO multiplexing will also be blocked, the blocking here is at the application level, that is, blocking in the multiplexing method, not at the operating system level.

2. Detailed explanation of common functions

1.int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds:  The total number of file descriptors listened on, which will be 1 greater than the maximum value of the file descriptor table in the file descriptor table set, because the file descriptors count from 0
readfds: The set of file descriptors for the readable events to be monitored (if there is any movement, the set will only retain the generated readable events). See the following example
writefds: Set of file descriptors of writable events to listen for
exceptfds: Set of file descriptors of the exception events to listen for
timeout: That is, tell the kernel select Give up waiting after waiting for how long. Generally set as NULL It means blocking and waiting without movement

2.set Correlation function, set Is an array of 1024, which can record each fd. 
FD_ZERO(fd_set* set)
Understood as initialization file descriptor geometry (Set all bits to 0)
FD_SET(fd,fd_set* set)
Add file descriptor to collection(Correspondence in essence fd Bit set to 1)
FD_CLR(fd,fd_set* set)
It is understood as taking the file descriptor out of the collection (essentially corresponding) fd (bit set to 0)
FD_ISSET(fd,fd_set* set)
It is understood to detect whether the modified file descriptor is in the set (essentially corresponding) fd Whether the bit is set to 1)

3. Server code

Code idea: create listenfd and place it in the fd collection set, call select blocking listener set set, when select returns, judge whether there is listenfd in set, if there is, there is new client to communicate with server, call accept to return to client and port and get a new one, put it in the middle. Continue to block the set listening to the select. If the returned set has listenfd, call accept to add the connfd of the new client to the set. If the returned set has connfd, communicate with the corresponding client.

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <signal.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#define SET_PORT 8000
int main(int argc, char *argv[])
{
    int sockfd,connfd;//Listen socket and connect socket
    struct sockaddr_in serveraddr;
    int i;//It is mainly used for i of various for loops
    int on = 1;//Only the reusable ports set below can be used
     //1. Create a listening socket
    sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ;//Set as reusable port
    
    //2.bind (socket is required for communication. I'll tie my home address and house number to ip and port)
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(SET_PORT);
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sockfd, (struct sockaddr *)&serveraddr,sizeof(serveraddr));
    //3. Sum of listening and server connection
    listen(sockfd,128) ;  
    int maxfd = sockfd;
    //Initializes two collections and an array
    int client[FD_SETSIZE];//The array is used to store the fd circular query of the customer service side_ SetSize is a macro with a maximum of 1024 by default
    fd_set rset;//Put it in the select, and there is always one fd in the set
    fd_set allset;//Add fd only
    FD_ZERO(&rset);//Empty action
    FD_ZERO(&allset);//Empty action
    
    //Put the listening socket into
    FD_SET(sockfd,&allset);
    int nready;
    
    //Initialization arrays are all - 1. Expected identifier, starting from 0
    for(i = 0; i < FD_SETSIZE; i++)
        client[i] = -1;
    while(1)
    {
    	//A crucial step
        rset = allset;//Ensure that the select loop can listen to all file descriptors every time, because there will only be dynamic ones left in rset
        nready = select(maxfd+1,&rset,NULL,NULL,NULL);//Parameter one
        
        //New client
        if(FD_ISSET(sockfd,&rset))
        {
            struct sockaddr_in clientaddr;  
            memset(&clientaddr,0,sizeof(clientaddr));
            int len = sizeof(clientaddr);
            
            connfd = accept(sockfd, (struct sockaddr*)&clientaddr,&len);
            
            char ipstr[128];//Used for printing
            printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)),
                   ntohs(clientaddr.sin_port));
            
            //One thing to do: put the file df into the array
            for(i = 0; i < FD_SETSIZE; i++)
            {	if(client[i] < 0)
                {
                    client[i] = connfd;
                    break;//Be sure to jump out of the error prone point in time
                }
            }
            //The second thing to do: put it into the collection
            FD_SET(connfd,&allset);//Put into collection
            //Prevent out of range / / the first parameter of select must be the monitored file descriptor + 1. If there are new client connections and the maximum value is getting larger and larger, it will be assigned
            if(connfd > maxfd)
                maxfd = connfd;
            
            //The following indicates that if there is only one movement at the same time, there is no need to enter the lower else judgment processing. If there is more than one nready-1, enter the lower judgment again
            if(--nready <= 0)  
            	continue;
            
        }
        else
        {
            //Connected FD generates readable event
            for(i = 0; i < FD_SETSIZE; i++)//FD_SEISIZE is the macro 1024 / / loop to get the element comparison from the array
            {		
                
                if(FD_ISSET(client[i],&rset))
                {
                    connfd = client[i];
                    char buf[1024] = {0};
                    int nread ;
                    nread = read(connfd, buf, sizeof(buf));
                    if(nread == 0)//Indicates that the customer service end is disconnected
                    {
                        //Four step processing print description delete from set delete from array close customer service end
                        printf("client is close..\n");
                        FD_CLR(connfd, &allset);
                        client[i] = -1;
                        close(connfd);
                    }
                    else//Normal read processing
                    {
                        write(connfd,buf,nread);
                        memset(buf,0,1024); 
                        
                    }
                   //The following indicates that if the time is agreed, if there is only one readable event, there is no need to cycle the array elements and jump out directly
                    //Don't waste time by letting the cycle go
                    if(--nready <= 0)
                        break;
                }
            }
        }
    }    
    return 0;
}


III epool

1. The difference between epool and select

epoll does not exist for the set_ Create will return an fd indicating that the space contains all the events (structures)
epoll packages every fd to be monitored into an event, and records this event in epollfd for epollfd to monitor
select generates movement, right? fd is put into the set, but epoll passes epoll_wait puts the events wrapped by the fd that generates the dynamic and static into the structure array
select needs to be backed up and the array needs to be recreated for fd cyclic comparison. epoll can obtain fd directly through packaged events (structures), and the efficiency is faster (the difference is mainly reflected in this)
The difference between the two is that select is suitable for the situation where there are few customer service clients, while epoll has no upper limit of clients

2. Common functions

#include <sys/epoll.h>

int epoll_create(int size);
Function: create a epoll Handle, which tells him the number of sockets that need to be monitored (it can also be understood as applying for a space to store the monitored socket)

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
Function: control a epoll Events on the monitored file descriptor: registration, modification and deletion (that is, adding, deleting and modifying an event)

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
Function: monitor the events on the red black tree and put the events that generate movement on the event In this array,


int epoll_create(int size);
Parameter 1: notify kernel to listen size individual fd,It is only a recommended value and has something to do with the hardware. (from Linux Kernel 2.6.8 From version, size This parameter is ignored and only requires size Greater than 0)
Return value: Return epoll Handle( fd)

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
Parameter 1: int epfd:epoll_create()Return value of
 Parameter 2: int op:  Represents an action, represented by three macros
EPOLL_CTL_ADD(Register new fd reach epfd)
EPOLL_CTL_MOD(Modify registered fd Listening events)
EPOLL_CTL_DEL(from epfd Delete a fd)
Parameter 3: int fd Operation object( socket)
Parameter 4: struct epoll_evevt* evevt; Tell the kernel what events to listen for

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
Parameter 1: int epfd:epoll_create()Function return value
 Parameter 2: struct epoll_events* events An array used to pass back the processing events (that is, to store the events that generate movement)
Parameter three:int maxevents Tell the kernel how many events are generated at most at the same time events The value must be greater than 0
 Parameter four:int timeout express -1 Equivalent to blocking, 0 equivalent to non blocking, timeout(Unit: ms)
Return value: the number of dynamic and static events successfully returned


	struct epoll_event {
	__uint32_t events; Macro definition read and write EPOLLIN read EPOLLOUT,Edge trigger EPOLLET					
	epoll_data_t data; Consortium
	};
	
	The consortium is as follows:
	typedef union epoll_data {
	void *ptr;//This pointer can point to a structure with a function. When a corresponding event occurs, the function in the structure pointed to by the secondary pointer can be called manually. This is the reactor model.
	int fd;  //Generally, this fd determines whether it is the corresponding listenfd or connfd to determine whether there is a new client link and which old client is sending data
	__uint32_t u32;
	__uint64_t u64;
	} epoll_data_t;

Edge Triggered (ET) Edge trigger is triggered only when data arrives, regardless of whether there is data in the cache.
Level Triggered (LT) Horizontal trigger will be triggered as long as there is data


3. Service area code

Code idea: epool_create creates a red black tree, returns epollfd and points to the red black tree. Set the event structure of listenfd and call epool_ctl will listen fd to the tree, epool_wait monitors fd and epool on the tree_ When there is a response to wait, use epool_ Outgoing parameter struct epoll of wait_ Event * Events Check fd. If listenfd in events indicates that a new client communicates with the server, then call accept to get the ip and port of connfd and client, and upload the new connfd to the tree, and then listen to the red black tree. When there is an old client communicating, use connfd to communicate with it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define MAXLINE 80
#define SERV_PORT 8000 / / port number
#define OPEN_MAX 1024 / / maximum connections



int main(int argc,char *argv[])
{	
	int maxi,sockfd,connfd;//sockfd is used to listen to the connection socket used by connfd. To listen to the socket, you need to create a connection socket and wait for it to return. Socket is not required
	int nready,efd; //efd is the dynamic and static number generated by epoll model identifier nready
	struct sockaddr_in clientaddr, serveraddr;
	struct epoll_event event, events[OPEN_MAX]; //One fruit basket, one structure
	
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&serveraddr, sizeof(serveraddr));
	bzero(&clientaddr, sizeof(clientaddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(SERV_PORT);
	int on =1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ;//Set as reusable port
    bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr));
    listen(sockfd, OPEN_MAX);//Server Socket 
	efd=epoll_create(OPEN_MAX);
	/*Wrapper server fd is an event*/
	event.events=EPOLLIN|EPOLLET;
	event.data.fd=sockfd;
    epoll_ctl(efd,EPOLL_CTL_ADD,sockfd,&event);//Wrap the server fd as an event and put it on the red black tree	
    while(1)
	{
		//Parameter 1 epollfd parameter 2 array of structures generating dynamic and static parameters parameter 3 maximum number of dynamic and static parameters generated at the same time
		nready=epoll_wait(efd,events,OPEN_MAX,-1);//The return value is the dynamic and static quantity
		for(int i=0;i<nready;i++)
		{        	
			if(!(events[i].events & EPOLLIN))//It is judged that the readable event does not return the loop immediately, which is different from select
				continue;
			if (events[i].data.fd==sockfd)//Indicates a new connection
			{
				int len=sizeof(clientaddr);
				char ipstr[128];//Used for printing
				connfd=accept(sockfd,(struct sockaddr *)&clientaddr,&len);
				printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)),
					ntohs(clientaddr.sin_port));
				event.events = EPOLLIN|EPOLLET; 
				event.data.fd = connfd;  
				epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event);			
			}
			else//Indicates that the old data generates a readable event (1 data sent by the client 2 client disconnects)
			{				
     			connfd=events[i].data.fd;
				char buf [1024];
				memset(buf,0,1024);
				int nread;		
				nread=read(connfd,buf,sizeof(buf));
				
				if(nread==0)
				{
					printf("client is close..\n"); //Print
					epoll_ctl(efd, EPOLL_CTL_DEL, connfd, NULL);//Delete select is to delete from the collection and array
					close(connfd);//Closing the customer service end is the same as select ing
                }
				else
				{
					printf("%s",buf);
				}			
			}		
		}	
	}	
}

4, udp communication

1. Implementation method and its code

Select sock when creating socket_ For Dgram, udp protocol is selected. udp can be read and written at one time without stable link. Generally, recvfrom and sendto are directly used for reading and writing.

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
	 sockfd:  socket 
	 buf: buffer address 
	 len: Buffer size 
	 flags:  0
	 src_addr: (struct sockaddr *)&addr Outgoing. Peer address structure
	 addrlen: Incoming and outgoing. 
	 Return value: the number of bytes of data successfully received. Failed:-1 errn.  0:  The opposite end is closed.
   
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen); 
    sockfd:  socket 
    buf: Buffer for storing data 
    len: Data length 
    flags:  0 
    src_addr: (struct sockaddr *)&addr Incoming. Target address structure 
    addrlen: Address structure length. 
    Return value: the number of data bytes successfully written out. fail -1, errno

server end
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>

#define SERV_PORT 8000

int main(void)
{
    struct sockaddr_in serv_addr, clie_addr;
    socklen_t clie_addr_len;
    int sockfd;
    char buf[BUFSIZ];
    char str[INET_ADDRSTRLEN];
    int i, n;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(SERV_PORT);

    bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    printf("Accepting connections ...\n");
    while (1) {
        clie_addr_len = sizeof(clie_addr);
        n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len);
        if (n == -1)
            perror("recvfrom error");

        printf("received from %s at PORT %d\n",
                inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
                ntohs(clie_addr.sin_port));

        for (i = 0; i < n; i++)
            buf[i] = toupper(buf[i]);

        n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
        if (n == -1)
            perror("sendto error");
    }

    close(sockfd);

    return 0;
}

client end
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>

#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    int sockfd, n;
    char buf[BUFSIZ];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);

    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while (fgets(buf, BUFSIZ, stdin) != NULL) {
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if (n == -1)
            perror("sendto error");

        n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0);         //NULL: don't care about information
        if (n == -1)
            perror("recvfrom error");

        write(STDOUT_FILENO, buf, n);
    }

    close(sockfd);

    return 0;
}

5, Local socket

Socket(AF_UNIX, SOCK_STREAM, 0) select AF_ UNIX, local communication is selected.
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stddef.h>
#include "wrap.h"

#define SERV_ADDR  "serv.socket"

int main(void)
{
    int lfd, cfd, len, size, i;
    struct sockaddr_un servaddr, cliaddr;
    char buf[4096];
    lfd = Socket(AF_UNIX, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, SERV_ADDR);
    len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);     /* servaddr total len */
    unlink(SERV_ADDR);                              /* Make sure that serv The sock file does not exist. bind will create it */
    Bind(lfd, (struct sockaddr *)&servaddr, len);           /* Parameter 3 cannot be sizeof(servaddr) */

    Listen(lfd, 20);
    printf("Accept ...\n");
    while (1) {
        len = sizeof(cliaddr);  //AF_UNIX size + 108B

        cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len);

        len -= offsetof(struct sockaddr_un, sun_path);      /* Get the length of the file name */
        cliaddr.sun_path[len] = '\0';                       /* Make sure there is no garbled code when printing */

        printf("client bind filename %s\n", cliaddr.sun_path);

        while ((size = read(cfd, buf, sizeof(buf))) > 0) {
            for (i = 0; i < size; i++)
                buf[i] = toupper(buf[i]);
            write(cfd, buf, size);
        }
        close(cfd);
    }
    close(lfd);

    return 0;
}


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    int sockfd, n;
    char buf[BUFSIZ];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);
    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while (fgets(buf, BUFSIZ, stdin) != NULL) {
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if (n == -1)
            perror("sendto error");

        n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0);         //NULL: do not care about peer information
        if (n == -1)
            perror("recvfrom error");

        write(STDOUT_FILENO, buf, n);
    }

    close(sockfd);

    return 0;
}

Topics: Linux Android