1. Host and network endianness

The CPU’s accumulator (the register that holds the operands and results of arithmetic or logical operations) can load up to four bytes at a time (32-bit systems), so the order of the four bytes in memory will affect the final value it loads into the accumulator. This is a byte order problem

Big-endian (network endian): In accordance with people’s left-to-right reading, the most important bytes (23-31) are stored at the lower address of memory, and the least important bytes (0-7) are stored at the higher address of memory. Small endian (host endian): The high byte is stored at the high address of memory, and the low byte is stored at the low address of memory (reverse read order)

#include <stdio.h> // Check the machine's order void byteOrder () {union {short value; char union_bytes[ sizeof(short) ]; }test; test.value = 0x0102; If ((test.union_bytes[0] == 1) && (test.union_bytes[1] == 2)) {printf("big endian\n"); // If ((test.union_bytes[0] == 1) && (test.union_bytes[1] == 2)) {printf("big endian\n"); Else if((test.union_bytes[0] == 2) && (test.union_bytes[1] == 1)) {printf("little endian\n"); } else { printf("unknown... \n"); }}Copy the code

2. General and dedicated socket addresses

#include <bits/socket.h> struct sockaddr {sa_family_t sa_family; char sa_data[14]; };Copy the code

Common protocol families and corresponding address families are as follows: PF_UNIX -> AF_UNIX Local protocol family PF_INET -> AF_INET TCP/IPv4 protocol family PF_INET6 -> AF_INET6 TCP/IPv6 protocol family The same values can be used together

// Private socket address // this protocol family omitted... // IPv4 struct sockeaddr_in { sa_family_t sin_family; /* Address family */ u_int16_t sin_port; */ struct in_addr sin_addr; /* Address structure */}; struct in_addr { u_int32_t s_addr; /* IP address, network byte order representation */}; // IPv6 omitted...Copy the code

3. IP address translation

To convert to integer in programming, log using dotted decimal string conversion function omitted here…

4. Create a socket

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
Copy the code

Domain: the agreement

Type: SOCK_STREAM(stream service type, indicating that transport layer uses TCP), SOCK_UGRAM(datagram service type, indicating that transport layer uses UDP)

The type argument can be used with SOCK_NONBOLOCK and SOCK_CLOEXEC to set the socket to non-blocking and to close the socket when the child process is created by calling fork, respectively. These two properties can also be set by calling FCNTL

Protocol: Selects a protocol. The first two parameters already determine its value, so it is generally set to 0

5. Name the socket

The bind function returns 0 on success or -1 on failure and sets errno. Errno: EACCES: The bound address is a protected address accessible only to superusers, such as the well-known port EADDRINUSE bound to 0-1023: The bound address is in use, such as an address in TIME_WAIT state

6. Listening socket

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

Sockfd: indicates the socket backlog. If the backlog is larger than the maximum length of the listening queue, the server will not accept new connections and the client will receive ECONNREFUSED. If the socket upper limit is ESTABLISHED, 0 is returned on success, -1 is returned on failure, and errno is set

Telnet 192.168.0.1 / * establish connections on port 12345 * 12345 / netstat - nt | grep 12345 / * show listen to monitor the contents of a queue * /Copy the code

6. Accept connections

Accept fails by returning -1 and setting errno. Accept is unaware that the client network is disconnected. It simply pulls the connection from the listening queue, regardless of the state of the connection, and does not care about the changes in network condition

7. Initiate a connection

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* serv_addr, socketlen_t addrlen);
Copy the code

Sockfd: the client calls socket() to create the file descriptor returned by the function serv_addr: the server listens to the socket address addrlen: The address length returns 0 if the connection is successful. Sockfd uniquely identifies the connection, and the client can communicate with the server through sockfd. If no, -1 is returned and errno is set to the following: ECONNREFUSED: the destination connection is refused. ETIMEDOUT: The connection times out

8. Close the connection

#include <unistd.h>
int close(int fd);
Copy the code

The close call does not always close a connection immediately, but rather subtracts the reference count of the fd by one, and only closes the connection if the reference count of the FD is zero. The fork call increases the socket reference count in the parent process by one, so both parent processes should execute close to close the connection

int shutdown(int sockfd, int howto);
Copy the code

SHUT_RD: Shuts down the read. The application program no longer performs socket read operations, and the data in the read buffer is discarded. SHUT_RDWR: At the same time, 0 is returned on read/write success, -1 is returned on failure, and errno is set

9. TCP data read and write

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void* buf, size_t len, int flags);
ssize_t send(int sockfd, const void* buf, size_t len, int flags);
Copy the code

recv:

Read data on sockfd. Buf and len specify the location and size of the buffer. Flags is usually set to 0.

Recv successfully returns the actual length of bytes read, which may be less than the desired length, so recv is called multiple times. Return 0 means the communication partner has closed the connection error return -1 and set errno

send:

To write data to sockfd, buf and len specify the location and size of the buffer, and flag is usually set to 0

Returns the actual data length on success, and -1 and sets errno on failure

10. Read and write UDP data

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
Copy the code

Since there is no concept of connection, address must be specified for each call recvfrom: sender’s address sendto: receiver’s address

11. A socket option

The FCNTL system call is a generic POSIX method for controlling file descriptor properties. The following two methods are dedicated to reading and setting socket file descriptor properties:

#include <sys/socket.h>
int getsockopt(int sockfd, int level, int option_name, void* option_value, socketlen_t* restrict option_len);
int setsockopt(int sockfd, int level, int option_name, const void* option_value, scokelen_t option_len);
Copy the code

Level: SOL_SOCKET(common socket option, regardless of the protocol) Option name: SO_DEBUG: enables debugging SO_REUSEADDR: reuses the local address SO_TYPE: SO_RECVBUF: indicates the size of the receiving buffer. SO_SNDBUF: indicates the size of the sending buffer. SO_KEEPALIVE: indicates that periodic packets are sent to maintain the connection. SO_RCVLOWAT/SO_SNDLOWAT: low watermark for sending and receiving SO_RCVTIMEO/SO_SNDTIMEO: Time out for receiving and sending data

Level: IPPROTO_IP(IPv4 option) Option name: IP_TOS: service type IP_TTL: lifetime

Level: IPPROTO_IPV6(IPv6 option) Corresponding option name: ignore for now…

Level: IPPROTO_TCP(TCP option) Option name: TCP_MAXSEG: indicates the maximum size of a packet segment TCP_NODELAY: indicates the maximum size of a packet segment. Disable the Nagle algorithm to allow packets to be sent without waiting for the write buffer to accumulate enough to return 0 on success, -1 on failure and set errno. For the server, the socket option should be set for listening sockets before the LISTEN call. The connection socket returned by Accept inherits these options for listening on the socket. For the client, the socket option must be set before connect, since the TCP three-way handshake has been completed

SO_REUSEADDR option: The address bound to the socket can be reused immediately even if the socket is in TIME_WAIT state

12. Network information API

To be continued