Network programming (realize the mutual communication of LAN and send and receive data)

Posted by dsdsdsdsd on Sat, 12 Feb 2022 03:23:08 +0100

linux network programming

1, Understanding of ip and ports

  1. What is socket?

1). Socket is translated into socket, socket and row plug in English. (because there are many kinds of sockets, it seems that there are many protocols. These protocols must be consistent before communication can be carried out.)
Network programming - > socket programming, socket programming.

2). socket() is also a function interface.
The function function is to create a socket.

3). Socket also refers to socket word - > special file descriptor.

  1. What is an IP address?
    For example: 192.168.14.2 - > point by point system
    In a local area network, each host will have an IP address, and the IP address must be the same network segment - > it refers to that the first three digits of the IP address are the same.
    Each IP address is 32 bits. If the IP address is used in the network programming code, the 32-bit data must be converted into network bytes.
    (in short: the communication between computers requires an address. With an address, I can accurately communicate with Xiaoming's computer, which is equivalent to the house number in daily life. With a house number, I can find Xiaoming's home. If there is no IP address / house number, how can I communicate with Xiaoming's computer / find Xiaoming's home?)

  2. What is a port number?
    In a LAN, two hosts need to communicate. In addition to the IP address in the same network segment, they also need to use the same port number.
    (in fact, the port number is like QQ on the computer. The port number is actually the address of the application on the computer, because it is not enough for us to identify and find the corresponding computer host through the IP address, but also to find the corresponding application. The communication between QQ is actually the same port number, so why can't QQ communicate with wechat? Obviously, the port number is different)

                  host A              host B 
    

Network segment with the same IP address: 192.168.14.2 192.168.14.4
Same port number: 5000

The port number is 16 bits. If the port number is used in the code of network programming, the 16 bit data must be converted into network bytes.
Ports used by the system: 0 ~ 1023 (users cannot use)
User's valid port: 1024 ~ 65535 (user's free use) - > after using the port number, wait at least 1 minute before using it again.

  1. How to view and configure the IP address of ubuntu
    Check other information by yourself. There's no need to say more here.

2, Communication protocol ---- TCP

  1. TCP protocol features?
    Full name of TCP protocol: Tranmission Control Protocol
    Transmission control protocol

    TCP protocol communication is similar to making a phone call in reality. You must connect to communicate. - > TCP protocol is a reliable transmission mode.
    TCP protocol action scenario: account login and file transfer.

  2. Analyze the principle of TCP protocol.
    TCP protocol can connect normally because both parties follow the three-time handshake protocol.
    1) First handshake:
    When establishing a TCP connection, the client sends a syn packet (seq=j) to the server, and the client waits for the server to confirm.

    2) Second handshake:
    After receiving the syn packet, the server must confirm the SYN(ack=j+1) of the client. At the same time, the server will also send a syn packet (seq=k) to the client, that is, SYN+ACK. At this time, the server enters the waiting state.

    3) Third Handshake:
    The client receives the SYN+ACK packet sent by the server and wants the server to send a confirmation packet (ACK=k+1). After the packet is sent, the client and the server are connected.

  3. 1). Create TCP socket
    Interface declaration: int socket(int domain, int type, int protocol);

    Parameters:
    Domain: domain.

    AF_INET/PF_INET: Internet Protocol
    AF_UNIX/PF_UNIX: Local agreement, which can be written as AF_LOCAL/PF_LOCAL
    

    Type: type.

    SOCK_STREAM: stream socket 
    SOCK_DGRAM: Datagram Socket 
    

    Protocol: protocol.
    Generally 0

    Return value:
    Success: socket to be connected
    Failed: - 1

    Note: in the internet protocol, selecting streaming socket represents TCP protocol, and selecting packet socket represents UDP protocol. The third parameter protocol is generally not used.

    2) Bind IP address and port number
    Interface declaration: int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    Parameters:
    sockfd: socket to be connected
    addr: pointer to the universal address structure containing the local address (IP+PORT)
    addrlen: address structure size

    Return value:
    Success: 0
    Failed: - 1

    remarks:
    Definition of general address structure:

struct sockaddr
{
sa_family_t  sa_family;  -> agreement -> 2
char        sa_data[14];  -> IP,Port number..
};

Special address structure - IPv4 address structure:

struct sockaddr_in
{           
       u_short sin_family;	// Address family - > 2
       u_short sin_port;	// Port number - > 2
       struct in_addr sin_addr;	// IPV4 address - > 4
       char sin_zero[8];
};

   struct in_addr
{
in_addr_t s_addr;	// Unsigned 32-bit network address - > IP 
};

3) Set listening socket
Interface declaration: int listen(int sockfd, int backlog);

Parameters:
sockfd: socket to be connected
backlog: maximum number of connection requests received simultaneously

Return value:
Success: 0, and set sockfd to listen socket
Failed: - 1

4) Waiting for peer connection request
Interface declaration: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Parameters:
sockfd: listening socket
addr: general address structure, which is used to store the peer address (IP+PORT)
addrlen: storage area size of parameter addr

Return value:
Success: connected socket (non negative integer)
Failed: - 1

5) Receive data from TCP socket
Interface declaration: ssize_t recv(int sockfd, void *buf, size_t len, int flags);

Parameters:
sockfd: connected socket
buf: store data buffer
len: buffer size
flags: receive flag, which can be set to 0.

Return value:
Success: bytes received
Failed: - 1

6) Convert text address to binary address
Interface declaration: int inet_pton(int af, const char *src, void *dst);

Parameters:
af: address family. AF_INET: IPv4 address
src: pointer to "dotted" IPv4 or IPv6 address, such as "192.168.1.100"
dst: type struct in_ Pointer to addr *

Return value:
Success: 1
Failure: 0 means the address does not match the address family, - 1 means the address is illegal

7) Convert binary address to text address
Interface declaration: const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

Parameters:
af: address family.

AF_INET: IPv4 address
AF_INET6: IPv6 address

src: type struct in_addr * or struct in6_ Pointer to addr *
dst: address buffer pointer, buffer at least
Size: address buffer size, at least INET_ADDRSTRLEN or INET6_ADDRSTRLEN bytes

Return value:
Success: dst
Failed: NULL

8) Connect peer listening socket
Interface declaration: int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Parameters:
sockfd: socket to be connected
addr: pointer to the general address structure containing the opposite end address (IP+PORT)
addrlen: address structure size

Return value:
Success: 0
Failed: - 1

-Simply, we can understand the above content by analyzing two pieces of code

Server side (rose):
Compile:/ rose 50000
rose is the file name and 50000 is the port number

#include "head.h"

int main(int argc,char *argv[])  // ./rose 50000
{
	//1. Create TCP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_STREAM,0);//AF_INET: Internet Protocol SOCK_STREAM: socket stream
	printf("sockfd = %d\n",sockfd);
	
	//2. Bind IP address and port number
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,len);
	
	srvaddr.sin_family = AF_INET;  //Address family, AF_INET: Internet Protocol (ipv4 address)
	srvaddr.sin_port = htons(atoi(argv[1]));  //Port number htons: converts an unsigned short integer value to network byte order atoi: converts a string to an integer number
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP address / usr / include / Linux / in H / / htonl: convert the unsigned long integer number of the host to the network byte order
	                                //INADDR_ANY: refers to the current IP address of the server
	
	bind(sockfd,(struct sockaddr *)&srvaddr,len);  //Bind IP + port
	
	//3. Set listening socket
	//Before calling listen: sockfd - > socket to be connected
	listen(sockfd,5);
	//After calling listen: sockfd - > Listen socket
	
	//4. Wait for the client to connect
	struct sockaddr_in cliaddr;
	int connfd;
	
	connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);//Blocking waits for the client to establish a connection. If successful, a socket file descriptor successfully connected with the client is returned
	if(connfd >= 0)
	{
		printf("connfd = %d\n",connfd);
		printf("new connection:%s\n",inet_ntoa(cliaddr.sin_addr));
	}
	
	//5. Read data on socket
	char buf[100];
	while(1)
	{
		bzero(buf,sizeof(buf));
		//block
		recv(connfd,buf,sizeof(buf),0);//It is used to receive the data sent by the remote host through socket sockfd and save these data into the array buf.
		printf("from jack:%s",buf);
		
		if(strncmp(buf,"fenshou",7) == 0)
		{
			break;
		}
	}
	
	//6. Reclaim TCP socket resources
	close(sockfd);
	close(connfd);
	
	return 0;	
}

Client (jack):
Compile:/ jack 192.168.14.11 50000
jack: the program file name
192.168.14.11: IP address of the server
50000: port number (must be the same as the port number of the server)

#include "head.h"

int main(int argc,char *argv[])  // ./jack 192.168.14.11 50000
{
	//1. Create TCP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	printf("sockfd = %d\n",sockfd);
	
	//2. Prepare rose's IP address.
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,len);
	
	srvaddr.sin_family = AF_INET;  //Address family
	srvaddr.sin_port = htons(atoi(argv[2]));  //Port number
	inet_pton(AF_INET,argv[1],&srvaddr.sin_addr); //Set Rose's IP address
	
	
	//3. Initiate connection
	//Before the connect call: sockfd - > socket to be connected
	int ret = connect(sockfd,(struct sockaddr *)&srvaddr,len);
	if(ret == 0)
	{
		printf("connect success!\n");
	}
	//After the connect call: sockfd - > connected socket
	
	//4. Send data to rose
	char buf[100];
	
	while(1)
	{
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin); //Get the data from the keyboard and put it into the buffer buf
		
		send(sockfd,buf,strlen(buf),0); //It is used to send the data in buf to another host
		//Parameter: 1 Socket: Specifies the sender socket descriptor. 2.buf: indicates the buffer for storing sent data. 3.strlen actual number of bytes to be sent, 4 The fourth parameter is generally set to zero
		
		//If you enter fenshou on the keyboard, you exit
		if(strncmp(buf,"fenshou",7) == 0)
		{
			break;
		}
	}
	
	//5. Reclaim TCP socket resources
	close(sockfd);
	
	return 0;
}



/*In main(int argc,char *argv []);
  argc Indicates the number of parameters during execution
  argv[]Represents one of the execution parameters
  Suppose a program is my When I execute. Exe, I/ my ss yy
  argc is 3, argv[0] is my,argv[1] is ss,argv[2] is yy
  
  Also in this code, argv[1] and argv[2] in line 16 and 17 refer to the comments in the third line
  This file executes/ jack 192.168.14.11 50000, so it's easy to get the principle of this generation of program from now on
 */

  • Of course, the above code can only realize that the client sends data to the server one way
  • To realize two-way data sending and receiving, a little bit of system programming > thread knowledge is involved. The following code is provided

Server side:

#include "head.h"

void *func(void *arg)
{
	int connfd = *(int *)arg;
	
	//Continuously receive data
	char buf[100];
	while(1)
	{
		bzero(buf,sizeof(buf));
		recv(connfd,buf,sizeof(buf),0);
		printf("from client:%s",buf);
		if(strncmp(buf,"quit",4) == 0)
		{
			exit(0);
		}
	}
}

int main(int argc,char *argv[]) // ./server 50001
{
	//1. Create TCP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	
	//2. Bind IP address to socket
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,len);
	
	srvaddr.sin_family = AF_INET; 
	srvaddr.sin_port = htons(atoi(argv[1]));
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	bind(sockfd,(struct sockaddr *)&srvaddr,len);
	
	//3. Set listening socket
	listen(sockfd,5);
	
	//4. Keep waiting for the other party's connection
	struct sockaddr_in cliaddr;
	int connfd;
	connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);
	if(connfd > 0)
	{
		printf("new connection:%s\n",inet_ntoa(cliaddr.sin_addr));
	}
	
	//5. Create sub thread
	pthread_t tid;
	pthread_create(&tid,NULL,func,(void *)&connfd);
	
	//6. Continuously send data to the client
	char buf[100];
	while(1)
	{
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
		send(connfd,buf,strlen(buf),0);
		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}
	}
	
	close(sockfd);
	close(connfd);
	return 0;
}

client:

#include "head.h"

void *func(void *arg)
{
	int sockfd = *(int *)arg;
	char buf[100];
	while(1)
	{
		bzero(buf,sizeof(buf));
		recv(sockfd,buf,sizeof(buf),0);
		printf("from server:%s",buf);
		if(strncmp(buf,"quit",4) == 0)
		{
			exit(0);
		}
	}
}

int main(int argc,char *argv[])  // ./jack 192.168.14.4 50000
{
	//1. Create TCP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	printf("sockfd = %d\n",sockfd);
	
	//2. Prepare rose's IP address.
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,len);
	
	srvaddr.sin_family = AF_INET;  //Address family
	srvaddr.sin_port = htons(atoi(argv[2]));  //Port number
	inet_pton(AF_INET,argv[1],&srvaddr.sin_addr); //Set Rose's IP address
	
	
	//3. Initiate connection
	//Before the connect call: sockfd - > socket to be connected
	int ret = connect(sockfd,(struct sockaddr *)&srvaddr,len);
	if(ret == 0)
	{
		printf("connect success!\n");
	}
	//After the connect call: sockfd - > connected socket
	
	//Create thread
	pthread_t tid;
	pthread_create(&tid,NULL,func,(void *)&sockfd);
	
	//4. Send data to rose
	char buf[100];
	
	while(1)
	{
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
		
		send(sockfd,buf,strlen(buf),0);
		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}
	}
	
	//5. Reclaim TCP socket resources
	close(sockfd);
	
	return 0;
}


I Communication protocol. – UDP protocol
TCP -> Tranmission Control Protocol
UDP -> User Data Protocol
IP -> Internet Protocol

  1. What is the difference between TCP protocol and UDP protocol?
    TCP protocol is a reliable transmission method for connected situations. - > You must be connected to communicate.
    UDP protocol is an unreliable transmission mode for connectionless situations. - > You can send data without a connection.

  2. How?
    UDP protocol - > similar to writing letters.

2, Implementation process.

  • The server:
    //1. Create UDP socket
    int sockfd;
    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    //2. Binding.
    bind(sockfd,(struct sockaddr *)&srvaddr,len);

    //3. Wait for the other party's data.
    recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&cliaddr,&len);

    //4. close
    close(sockfd);

  • client:
    //1. Create UDP socket
    int sockfd;
    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    //2. Just send data directly.
    sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&srvaddr,len);

    //3. close
    close(sockfd);

  • Two new things we need to know

  1. Receive data from UDP socket
    Interface declaration: ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
    struct sockaddr *src_addr, socklen_t *addrlen);

    Parameters:
    sockfd: UDP socket
    buf: store data buffer
    len: buffer size
    Flags: receive flag, which is completely consistent with the flags of the function send
    src_addr: peer network address
    addrlen: address length

    Return value:
    Success: bytes received
    Failed: - 1

  2. Send data to UDP socket
    Interface declaration: ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
    const struct sockaddr *dest_addr, socklen_t addrlen);

    Parameters:
    sockfd: UDP socket
    buf: data to be sent
    len: length of data
    Flags: send flag, which is completely consistent with the flags of the function send
    dest_addr: peer network address
    addr_len: address length

    Return value:
    Success: bytes sent
    Failed: - 1

  • The following is the code of UDP communication
    Server side:
#include "head.h"

int main(int argc,char *argv[])  //./rose 50002
{
	//1. Create UDP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	
	//2. Bind IP address, port number and address family to UDP socket
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,sizeof(srvaddr));
	
	srvaddr.sin_family = AF_INET;//Address family
	srvaddr.sin_port = htons(atoi(argv[1]));//Port number
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP address / usr / include / Linux / in h
	
	//Bind ip + port
	bind(sockfd,(struct sockaddr *)&srvaddr,len);
	
	//3. Keep waiting for the client to send data to itself
	char buf[100];
	struct sockaddr_in cliaddr;
	while(1)
	{
		//Empty buffer
		bzero(buf,sizeof(buf));
		//Waiting for the other party's data
		recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&cliaddr,&len); . 
		printf("from jack:%s",buf);
		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}
	}
	
	//4. Recycling
	close(sockfd);
	
	return 0;	
}

client:

#include "head.h"

int main(int argc,char *argv[])  //./rose 192.168.14.4 50002
{
	//1. Create UDP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	
	//2 prepare rose's address.
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,sizeof(srvaddr));
	
	srvaddr.sin_family = AF_INET;//Address family
	srvaddr.sin_port = htons(atoi(argv[2]));//Port number
	inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);//Set rose's address
	
	//3. Keep writing to rose.
	char buf[100];
	while(1)
	{
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);//Enter data from the keyboard
		
		//Send data directly
		sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&srvaddr,len);
		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}
	}
	
	//4. Recycling resources
	close(sockfd);
	
}

  1. What is the IO model?
    Network programming for data output and input methods: blocking IO, non blocking IO, multiplexing, signal driving.

  2. How do these IO models work?
    1) Blocking IO: always blocking and waiting for the data of a socket to arrive. If there is data, it will be read and returned. If there is no data, it will always wait.
    read(fd);
    recv(fd);
    accept(sockfd);
    In the past, we all thought that the above examples were blocked by functions, such as read function and accept function, but it is wrong to think so, because the real blocking is the socket / file descriptor, not the function itself.

    Because fd is the file descriptor - > fd is the blocking attribute by default - > read (fd) - > blocking

2, Non blocking IO

  1. If you want to use non blocking IO, what is the idea?
    1) First create a file descriptor / socket - > blocking attribute by default.
    2) Set the non blocking attribute to the file descriptor - > at this time, the file descriptor is non blocking.
    3) When you call read()/accept()/recv() to process the file descriptor, it will be non blocking.

  2. How to set non blocking attribute to file descriptor? - > fcntl() -> man 2 fcntl

    Header file:
    #include <unistd.h>
    #include <fcntl.h>

    Prototype:
    int fcntl(int fd, int cmd, ... /* arg */ );

    Parameters:
    fd: the file descriptor for which the attribute needs to be set

    cmd:

 F_GETFL (void)  -> void Represents the third parameter, which does not need to be filled in
     Get the file access mode and the file status flags; arg is ignored.
     //Gets the properties of the current file descriptor
F_SETFL (int)   -> int It means that the following parameter needs to be filled in
    Set the file status flags to the value specified by arg.

O_NONBLOCK   -> Non blocking attribute

Return value:
success:
F_GETFL returns the properties of the file
F_SETFL returned 0

Failed:
	-1
  • Let's understand it through a piece of code

Server side

#include "head.h"

int main(int argc,char *argv[])
{
	//1. Create a TCP socket
	int sockfd;
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	
	//2. Bind IP address and port number
	struct sockaddr_in srvaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr,len);
	
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(atoi(argv[1]));
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	bind(sockfd,(struct sockaddr *)&srvaddr,len);
	
	//3. Set listening socket
	listen(sockfd,5);
	
	//Sockfd - > blocking attribute by default
	
	//4. Add non blocking attribute to sockfd
	int state;
	state = fcntl(sockfd,F_GETFL); //state is the current property of sockfd.
	state |= O_NONBLOCK;           //state is the new attribute
	fcntl(sockfd,F_SETFL,state);
	
	//Sockfd - > has non blocking attribute
	
	//5. Wait for the client to connect
	struct sockaddr_in cliaddr;
	bzero(&cliaddr,len);
	int connfd;
	
	while(1)
	{
		connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);
		if(connfd > 0) //If someone connects, it will return success
		{
			printf("connfd = %d\n",connfd);
			printf("new connection:%s\n",inet_ntoa(cliaddr.sin_addr));
			break;
		}
		else{ //If no one connects, failure will be returned
			printf("connect error!\n");
		}
	}
		
	close(sockfd);
	close(connfd);

	return 0;
}

Topics: network socket