In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
Editor to share with you the example analysis of Socket programming, I believe that most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!
1. How do processes communicate in the network?
There are many ways of local interprocess communication (IPC), but they can be summarized into the following four categories:
Messaging (pipes, FIFO, message queues) synchronization (mutexes, condition variables, read-write locks, file and write record locks, semaphores) shared memory (anonymous and named) remote procedure calls (Solaris gates and Sun RPC)
But these are not the theme of this article! What we are going to discuss is how processes communicate with each other in the network. The first problem to solve is how to uniquely identify a process, otherwise communication is out of the question! It is possible to uniquely identify a process locally through the process PID, but this does not work in the network. In fact, the TCP/IP protocol family has helped us solve this problem. The ip address of the network layer can uniquely identify the host in the network, while the "protocol + port" of the transport layer can uniquely identify the application (process) in the host. In this way, the triple (ip address, protocol, port) can be used to identify the process of the network, and the process communication in the network can use this flag to interact with other processes.
Applications that use the TCP/IP protocol usually use the API: UNIX BSD's socket (socket) and UNIX System V's TLI (which has been eliminated) to communicate between network processes. At present, almost all applications use socket, and now it is the network age, where process communication is ubiquitous, which is why I say "everything is socket".
2. What is Socket?
We already know that processes in the network communicate through socket, so what is socket? Socket originated from Unix, and one of the basic philosophies of Unix/Linux is "everything is a file", which can be operated in the "Open open-> read and write write/read-> close close" mode. My understanding is that Socket is an implementation of this pattern, socket is a special file, and some socket functions operate on it (read / write IO, open, close), which we will introduce later.
The origin of the word socket
The first use in the field of networking was found in the literature IETF RFC33 published on February 12, 1970, written by Stephen Carr, Steve Crocker and Vint Cerf. According to the American Museum of computer History, Croker wrote: "Namespace elements can be called socket interfaces. A socket interface forms one end of a connection, and a connection can be completely defined by a pair of socket interfaces." The computer History Museum added: "this is about 12 years earlier than the definition of BSD's socket interface."
3. Basic operation of socket
Since socket is an implementation of the "open-write/read-close" pattern, socket provides functional interfaces for these operations. Let's take TCP as an example to introduce several basic socket interface functions.
3.1.The socket () function
Int socket (int domain, int type, int protocol)
The socket function corresponds to the opening operation of a normal file. The opening of a normal file returns a file description, while socket () is used to create a socket descriptor (socket descriptor) that uniquely identifies a socket. This socket description word is the same as the file description word, the subsequent operations are useful to it, take it as a parameter, through it to do some read and write operations.
Just as you can pass in different parameter values to fopen to open different files. When you create a socket, you can also specify different parameters to create different socket descriptors. The three parameters of the socket function are:
Domain: protocol domain, also known as protocol family (family). The commonly used protocol families are AF_INET, AF_INET6, AF_LOCAL (or AF_UNIX, Unix domain socket), AF_ROUTE and so on. The protocol family determines the address type of socket, and the corresponding address must be used in communication. For example, AF_INET decides to use the combination of ipv4 address (32-bit) and port number (16-bit), and AF_UNIX decides to use an absolute path name as the address. Type: specifies the socket type. The commonly used socket types are SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_PACKET, SOCK_SEQPACKET, and so on (what are the types of socket? ). Protocol: therefore, the name "thought" means to specify the agreement. The commonly used protocols are IPPROTO_TCP, IPPTOTO_UDP, IPPROTO_SCTP, IPPROTO_TIPC, etc., which correspond to TCP transport protocol, UDP transport protocol, STCP transport protocol, and TIPC transport protocol (I will discuss this protocol separately! ).
Note: the above type and protocol can not be combined at will, for example, SOCK_STREAM cannot be combined with IPPROTO_UDP. When protocol is 0, the default protocol corresponding to the type type is automatically selected.
When we call socket to create a socket, the returned socket description exists in the address family,AF_XXX space, but does not have a specific address. If you want to assign an address to it, you must call the bind () function, otherwise the system will automatically randomly assign a port when connect () and listen () are called.
3.2.The bind () function
As mentioned above, the bind () function assigns a specific address in an address family to socket. For example, the corresponding AF_INET and AF_INET6 assign a combination of ipv4 or ipv6 address and port number to socket.
Int bind (int sockfd, const struct sockaddr * addr, socklen_t addrlen)
The three parameters of the function are:
Sockfd: the socket description word, which is created by the socket () function and uniquely identifies a socket. The bind () function simply binds a name to the descriptor.
Addr: a const struct sockaddr * pointer to the protocol address to bind to sockfd. This address structure varies according to the address protocol family in which the socket is created, for example, ipv4 corresponds to:
Struct sockaddr_in {sa_family_t sin_family; / * address family: AF_INET * / in_port_t sin_port; / * port in network byte order * / struct in_addr sin_addr; / * internet address * /}; / * Internet address. * / struct in_addr {uint32_t saddr; / * address in network byte order * /}
Ipv6 corresponds to:
Struct sockaddr_in6 {sa_family_t sin6_family; / * AF_INET6 * / in_port_t sin6_port; / * port number * / uint32_t sin6_flowinfo; / * IPv6 flow information * / struct in6_addr sin6_addr; / * IPv6 address * / uint32_t sin6_scope_id; / * Scope ID (new in 2.4) * /}; struct in6_addr {unsigned char s6_addr [16]; / * IPv6 address * /}
The Unix domain corresponds to:
# define UNIX_PATH_MAX 108struct sockaddr_un {sa_family_t sun_family; / * AF_UNIX * / char sun_ path [Unix _ PATH_MAX]; / * pathname * /}
Addrlen: corresponds to the length of the address.
Usually, when the server starts up, it will bind a well-known address (such as ip address + port number) to provide services, so that customers can connect to the server through it; while the client does not need to specify, the system automatically assigns a combination of port number and its own ip address. This is why bind () is usually called by the server before listen, but not by the client, but is randomly generated by the system when connect ().
Network byte order and host byte order
Host byte order is what we usually call large-end and small-end modes: different CPU have different types of byte order, which refers to the order in which integers are stored in memory, which is called host order. The definitions of Big-Endian and Little-Endian that reference the standard are as follows:
A) Little-Endian means that low-order bytes are placed on the low-address side of memory, while high-order bytes are placed on the high-address side of memory.
B) Big-Endian means that the high-order bytes are placed on the low address side of the memory, and the low-order bytes are placed on the high address side of the memory.
Network byte order: 4-byte 32 bit values are transmitted in the following order: first 0~7bit, then 8~15bit, then 16~23bit, and finally 24~31bit. This transmission order is called large-end byte order. Because all binary integers in the header of TCP/IP are required to be transmitted in this order in the network, it is also called network byte order. Byte order, as the name implies, is the order in which data of more than one byte type is stored in memory, and one byte of data is out of order.
So: when binding an address to socket, first convert the host byte order to the network byte order, instead of assuming that the host byte order uses the same Big-Endian as the network byte order. Because of this problem, there has been a murder! Because of this problem in the company project code, there are a lot of inexplicable problems, so please remember not to make any assumptions about the host byte order, be sure to convert it to network byte order and assign it to socket.
3.3.The listen (), connect () functions
As a server, after calling socket () and bind (), listen () will be called to listen to the socket, and if the client calls connect () to make a connection request, the server will receive the request.
Int listen (int sockfd, int backlog); int connect (int sockfd, const struct sockaddr * addr, socklen_t addrlen)
The first parameter of the listen function is the socket description word to listen for, and the second parameter is the maximum number of connections that the corresponding socket can queue. The socket created by the socket () function is an active type by default, and the listen function turns the socket into a passive type, waiting for a connection request from the customer.
The first argument to the connect function is the client's socket description, the second is the server's socket address, and the third is the length of the socket address. The client establishes a connection to the TCP server by calling the connect function.
3.4.The accept () function
After the TCP server calls socket (), bind (), and listen () in turn, it listens for the specified socket address. After calling socket () and connect (), the TCP client sends a connection request to the TCP server. After the TCP server listens to the request, it calls the accept () function to receive the request, so the connection is established. After that, you can start the network Iamp O operation, which is similar to the read and write Imax O operation of ordinary files.
Int accept (int sockfd, struct sockaddr * addr, socklen_t * addrlen)
The first parameter of the accept function is the socket description word of the server, the second parameter is the pointer to struct sockaddr *, which returns the protocol address of the client, and the third parameter is the length of the protocol address. If the accpet succeeds, its return value is a completely new description word automatically generated by the kernel, representing the TCP connection to the returned customer.
Note: the first argument to accept is the server's socket description word, which is generated when the server starts calling the socket () function, which is called listening for the socket description word, while the accept function returns the connected socket description word. A server usually only creates a listener socket description, which exists throughout the server's lifetime. The kernel creates a connected socket description word for each client connection accepted by the server process. When the server finishes serving a client, the corresponding connected socket description word is closed.
3. 5, read (), write () and other functions
Everything is available only to Dongfeng, so the server has established a connection with the customer. You can call the network Imax O for read and write operations, that is, to achieve the communication between different processes in the network! There are several groups of network Icano operations:
Read () / write ()
Recv () / send ()
Readv () / writev ()
Recvmsg () / sendmsg ()
Recvfrom () / sendto ()
I recommend using the recvmsg () / sendmsg () function, which is the most generic Imax O function, and can actually replace all the other functions above with these two functions. Their statements are as follows:
# include ssize_t read (int fd, void * buf, size_t count); ssize_t write (int fd, const void * buf, size_t count); # include # include ssize_t send (int sockfd, const void * buf, size_t len, int flags); ssize_t recv (int sockfd, void * buf, size_t len, int flags); ssize_t sendto (int sockfd, const void * buf, size_t len, int flags, const struct sockaddr * dest_addr, socklen_t addrlen) Ssize_t recvfrom (int sockfd, void * buf, size_t len, int flags, struct sockaddr * src_addr, socklen_t * addrlen); ssize_t sendmsg (int sockfd, const struct msghdr * msg, int flags); ssize_t recvmsg (int sockfd, struct msghdr * msg, int flags)
The read function is responsible for reading content from fd. When the read is successful, read returns the number of bytes actually read. If the returned value is 0, the end of the file has been read, and less than 0 indicates that an error has occurred. If the error is EINTR, it indicates that the read is caused by an interrupt, and if it is ECONNREST, there is a problem with the network connection.
The write function writes the nbytes byte contents of buf to the file descriptor fd. Returns the number of bytes written on success. Returns-1 on failure and sets the errno variable. In a network program, there are two possibilities when we write to a socket file descriptor. 1) the return value of write is greater than 0, indicating that some or all of the data has been written. 2) the returned value is less than 0, and an error occurs. We have to deal with it according to the type of error. If the error is EINTR, an interrupt error occurred while writing. If EPIPE indicates that there is a problem with the network connection (the other party has closed the connection).
I will not introduce these pairs of Imax O functions one by one, see the man documentation or baidu or Google. Send/recv will be used in the following examples.
3.6.The close () function
After the connection between the server and the client is established, some read and write operations will be carried out. When the read and write operation is completed, the corresponding socket description words will be closed, just like calling fclose to close the open file after the operation of the open file.
# include int close (int fd)
Close the default behavior of a TCP socket marks the socket as closed and then immediately returns to the calling process. This description can no longer be used by the calling process, that is, it can no longer be used as the first parameter of read or write.
Note: the close operation only causes the reference count of the corresponding socket description word to be-1. Only when the reference count is 0 will the TCP client be triggered to send a termination request to the server.
4. Detailed explanation of establishing connection by three-way handshake of TCP in socket
We know that tcp needs a "three-way handshake" to establish a connection, that is, to exchange three packets. The general process is as follows:
The client sends a SYN J to the server
The server responds to a SYN K to the client and acknowledges ACK Junction 1 to SYN J
The client sends an acknowledgement to the server to ACK Knowled1.
There is only a three-way handshake, but which functions of socket do this three-way handshake take place? Please take a look at the following picture:
Figure 1. TCP three-way handshake sent in socket
As can be seen from the figure, when the client calls connect, the connection request is triggered and the SYN J packet is sent to the server, and the connect enters the blocking state; the server listens to the connection request, that is, it receives the SYN J packet, and calls the accept function to receive the request to send SYN K, ACK Junction 1 to the client, and the accept enters the blocking state; after the client receives the SYN K, ACK Junction 1 from the server, connect returns and acknowledges the SYN K When the server receives ACK knot 1, accept returns. At this point, the three-way handshake is complete and the connection is established.
Summary: the client's connect returns on the second time of the three-way handshake, while the server's accept returns on the third time of the three-way handshake.
5. Detailed explanation of the four-way handshake release connection of TCP in socket
The above describes the establishment process of the three-way handshake of TCP in socket and the socket functions involved. Now let's introduce the process of releasing a connection with a four-way handshake in socket. Take a look at the following figure:
Figure 2. TCP four-way handshake sent in socket
The process shown is as follows:
An application process first calls close to actively close the connection, and then TCP sends a FIN M
After receiving the FIN M, the other end performs a passive shutdown to confirm the FIN. Its reception is also passed to the application process as a file Terminator, because the reception of FIN means that the application process can no longer receive additional data on the corresponding connection.
After a while, the application process that receives the file Terminator calls close to close its socket. This causes its TCP to also send a FIN N
TCP, the source and sender that received the FIN, confirms it.
So there is a FIN and ACK in each direction.
6. An example (practice)
Having said so much, let's put it into practice. Let's write a simple server, client (using TCP)-the server has been listening to the local port 6666, and if it receives a connection request, it will receive the request and receive a message from the client; the client will establish a connection with the server and send a message.
Server-side code:
Server side
# include#include#include#include#include#include#include#define MAXLINE 4096int main (int argc, char** argv) {int listenfd, connfd; struct sockaddr_in servaddr; char buff [4096]; int n; if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) =-1) {printf ("create socket error:% s (errno:% d)\ n", strerror (errno), errno); exit (0);} memset (& servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET Servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons (6666); if (bind (listenfd, (struct sockaddr*) & servaddr, sizeof (servaddr)) =-1) {printf ("bind socket error:% s (errno:% d)\ n", strerror (errno), errno); exit (0);} if (listen (listenfd, 10) = =-1) {printf ("listen socket error:% s (errno:% d)\ n", strerror (errno), errno) Exit (0);} printf ("= waiting for client's request=\ n"); while (1) {if ((connfd = accept (listenfd, (struct sockaddr*) NULL, NULL)) =-1) {printf ("accept socket error:% s (errno:% d)", strerror (errno), errno); continue;} n = recv (connfd, buff, MAXLINE, 0); buff [n] ='\ 0mm; printf ("recv msg from client:% s\ n", buff); close (connfd) } close (listenfd);}
Client code:
Client
# include#include#include#include#include#include#include#define MAXLINE 4096int main (int argc, char** argv) {int sockfd, n; char recvline [4096], sendline [4096]; struct sockaddr_in servaddr; if (argc! = 2) {printf ("usage:. / client\ n"); exit (0);} if ((sockfd = socket (AF_INET, SOCK_STREAM, 0) < 0) {printf ("create socket error:% s (errno:% d)\ n", strerror (errno), errno) Exit (0);} memset (& servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons (6666); if (AF_INET, argv [1], & servaddr.sin_addr)
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.