Introduction to Socket Socket API under Linux System

0 Introduction

Socket socket is a method of inter-process communication, allowing data exchange between applications located on the same host (computer) or on different hosts connected by the network. This set of APIs has been ported to all Unix implementations and most other operating systems. Below we introduce several key socket APIs: socket, bind, listen, accept, connect.

1 Create a socket: socket()

The socket() system call creates a new socket.

#include <sys/socket.h>
int socket(int domain,int type,int protocol)//若返回-1说明出错

The domain parameter specifies the communication domain of the socket, which is generally defined as AF_INET, which means that it communicates on hosts connected by an IPv4 network.
The type parameter specifies the Socket type, which is generally defined as SOCK_STREAM, indicating that this is a streaming socket that provides a reliable two-way byte flow communication channel. It can also be designated as SOCK_DGRAM, indicating that this is a datagram socket. Since Linux kernel 2.6.27, the type parameter can be set to SOCK_NONBLOCK, which means this is a non-blocking socket; it can also be set to SOCK_CLOEXEC to achieve close-on-exec.
The protocol is generally specified as 0.

2 Bind the socket to an address: bind()

Bind() realizes binding the socket to an address, the parameter sockfd is the file descriptor returned by socket(), sockaddr is the address structure, including the protocol, ip address, and port number, which will be described in detail later.

#include <sys/socket.h>
int bind(int sockfd,struct sockaddr* addr,
socklen_t addrlen_t addrlen) //返回-1表示出错。

Bind involves a lot of knowledge, let's talk about it in detail below.

2-1 Network byte order

First review the knowledge of endianness. The IP address and port number are both integers. When these values ​​are transmitted on the network, there is a problem that different hardware structures store multi-byte integers in different orders, which are divided into big-endian storage and little-endian storage.
The so-called big-endian storage is to store the most significant bit of a number at a lower memory address. This storage method is more in line with our intuition. For example, there is a binary number 1000, and the highest 1 will have lower memory, similar to We read from left to right. Little-endian storage, in turn, stores the most significant bit of a number at a higher memory address. The hardware of the x86 architecture uses little-endian storage.
Since the port number and address must be transmitted between all hosts in the network, a standard byte order must be used, which is big-endian and is called network byte order. When we assign values ​​to the information of the bind address structure sockaddr, these values ​​are expressed according to the rules for finding the host, so it needs to be converted to network byte order, and these functions are usually used.

#include <arpa/inet.h>
uint16_t htons(uint16_t host_uint16)//主机字节序转网络字节序,short
uint32_t htonl(uint32_t host_uint32)//主机字节序转网络字节序,long
uint16_t ntohs(uint16_t net_uint16)//网络字节序转主机字节序,short
uint32_t ntohl(uint32_t net_uint16)//网络字节序转主机字节序,long

The function of the function is shown in the comment. In addition, a set of Linux unique endian conversion functions are added, and the name is changed from n (net) to be (big end).

#include <endian.h>
uint64_t htobe64(uint64_t data)//(无符号)64字节主机转网络:
uint64_t be64toh(uint64_t data)//(无符号)64字节网络转主机:
uint32_t htobe32(uint32_t data)//(无符号)32字节主机转网络:
uint32_t be32toh(uint32_t data)//(无符号)32字节网络转主机:
uint16_t htobe16(uint16_t data)//(无符号)16字节主机转网络:
uint16_t be16toh(uint16_t data)//无符号)16字节网络转主机:

2.2 Internet Socket address struct sockaddr_in

There are two types of Internet domain socket addresses: IPv4 and IPv6. Only IPv4 is introduced here. The IPv4 address structure is stored in sockaddr_in, as follows

#include <netinet.h>
struct in_addr
{
    
    
	in_addr_r s_addr;//无符号32位整数
}
struct sockaddr_in
{
    
    
	sa_family_t sin_family;//地址协议族,定义为整数,一般是AF_INET
	in_port_t sin_port;//short型整数 端口号,网络字节序。
	struct in_addr sin_addr;//IP地址,网络字节序
	unsigned char _pad[X];//
}

Note that the second parameter of bind is struct sockaddr, which is a general address structure. As mentioned earlier, there are two types of Internet domain socket addresses, IPv4 and IPv6, and there is another socket address sockaddr_un for communication in the kernel. In order to unify the three and convert them into a single type, sockaddr is defined. Its structure is as follows

struct sockaddr
{
    
    
	sa_family_t sa_family;
	char sa_data[14];
}

When using bind, sockaddr_in needs to be forcibly transferred.

2.3 inet_pton() and inet_ntop functions

These two functions are used to convert between the binary form and dotted decimal or hexadecimal string representation of IPv4 and IPv6 addresses.

#include <arpa/inet>
int inet_pton(int domain,const char *src_str,void *addrptr)
const char* inet_ntop(int domain,const void *addrptr,char *dst_str,size_t len);

2-4 Summary

Through the knowledge of the above three sections, the usage of bind function is very clear. In IPv4 communication, first we need a sockfd created by socket(), then define a struct sockaddr_in addr, and then assign values ​​to the structure.
When assigning, addr.sin_family is assigned to AF_INET under IPv4, addr.sin_port needs to convert a port number host to network byte order, addr.sin_addr.s_addr also needs to be converted to network byte order, or inet_pton can be used in dotted decimal notation. String assignment.

bind(sockfd,(sockaddr*)&addr,sizeof addr);//示例

3 Monitor access connection: listen()

listen() marks the stream socket referenced by sockfd as passive so that this socket can accept other active socket connections.

#include <sys/socket.h>
int listen(int sockfd,int backlog);

The purpose of the second parameter backlog of socket is this. When an active socket connects to sockfd, the connection request must be processed when the accept function (described later) is in a blocking waiting state. If it appears that accept is processing other active sockets and has not returned to the blocking waiting state, if a connection comes at this time, such a connection is called a pending connection.
The kernel will record the information of such pending connections so that accept will proceed with subsequent processing. The backlog parameter is used to limit the number of such pending connections. Pending connections within the number of backlogs can be processed immediately. The soft upper limit under Linux is 128. After kernel 2.4.45, it can be modified under /proc/sys/net/core/somaxconn.

4 Accept the connection: accpet

As mentioned earlier, listen() marks the stream socket referenced by sockfd as passive so that this socket can accept other active socket connections. The acceptance here is done by accept. If there is no pending connection when calling accept, it will block.

#include <sys/socket.h>
//若返回-1表示出错
int accept(int sockfd,strcut sockaddr *addr,socklen_t *addrlen);

The return value of accept is a new socket file descriptor. This socket will communicate with the socket that initiated the connection.
It is also worth noting that Linux supports a new system call accept4 after kernel 2.6.8. Its first three parameters are the same as accept, with an additional parameter flags. Through this parameter we can set the new socket to be non-blocking (SOCK_NONBLOCK) and close-on-exec (SOCK_CLOEXEC).

5 Connect to the peer socket: connect()

connect() is used to connect the socket referenced by the file descriptor to a listening socket. The second parameter represents an address information.

#include <sys/socket.h>
//若返回-1表示出错
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen)

6 summary

The above content summarizes the socket API commonly used under Linux. Using these sockets, TCP server-client network communication can be carried out. The specific process is shown in the figure below, which is similar to making a call.
Insert picture description here

Guess you like

Origin blog.csdn.net/MoonWisher_liang/article/details/107548129