Many books that introduce network programming will introduce the connect system call as follows: connect a specified socket on the local machine to a server socket with a specified address. The following is the definition of a connect system call:
Int connect (INT sockfd, const struct sockaddr * serv_addr, socklen_t addrlen );
The sockfd parameter is a socket descriptor on the local machine. In the kernel's system call function, this descriptor is converted to a struct Socket Structure bound to it. This is a real socket, represents the connected end in network communication. Serv_addr and addrlen are the address and address length of the server to be connected.
Therefore, with this understanding, connect will establish a connection between the local machine and the specified server. However, the connect operation does not trigger the network device to transmit any data to the peer end. It only performs some operations, such as routing rules and route tables, to fill in some information about the peer server in the struct Socket Structure. In this way, when sending data reports to the peer end, you do not need to perform route query and other operations each time to determine the peer address information and the local sending interface, the application does not need to input the peer address information each time (you can use send instead of sendto ). Based on this understanding, we don't have to figure out why TCP socket can connect, UDP, and raw socket can also be connected through connect. There is actually no difference in their nature: cache the address information of the Peer host obtained through route query to the socket structure struct socket.
The UDP and raw connect operations are actually exactly the same. Both use the myip4_datagram_connect function.
For convenience, let's use another actual example to describe what the function is doing. We send a UDP datagram to port 16000 of host 172.16.48.2 on host 172.16.48.2, the UDP port on 172.16.48.2 is automatically selected by the system (32768 ). The following is a simple application example:
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <sys/IOCTL. h>
# Include "my_inet.h"
# Include <stdio. h>
# Include <errno. h>
# Include <ARPA/inet. h>
# Include <unistd. h>
Int main ()
{
Int I;
// Represents the structure of the server address.
Struct sockaddr_in DEST;
DeST. sin_family = my_pf_inet;
DeST. sin_port = htons (16000 );
DeST. sin_addr.s_addr = 0x013010ac; // network byte sequence of 172.16.48.1.
Int FD = socket (my_pf_inet, sock_dgram, my_ipproto_udp );
If (FD <0 ){
Perror ("socket :");
Return-1;
}
// Connection operation.
If (connect (FD, (struct sockaddr *) & DEST, sizeof (DEST) <0)
Perror ("Connect :");
// You do not need to pass the peer address information through sendto each time.
Int bwrite = Send (FD, "abcdefg", 7, 0 );
If (bwrite =-1 ){
Perror ("Send :");
Return-1;
}
Printf ("sendto: % d \ n", bwrite );
Close (FD );
Return 0;
}
The execution stream called by the connect system has automatically selected the local port number before it reaches the myip4_initram_connect function and bound the socket to the myudp_hash table. After arriving at the myip4_mongoram_connect function, the first thing is to create a struct flowi:
Struct flowi FL = {. OIF = 0, // The output device interface is not fixed.
. Nl_u = {. ip4_u = {. daddr = 172.16.48.1 // destination address.
. Saddr = 0.0.0.0 // the source address is not fixed.
. TOS = 0 }}, // General Service
. Proto = my_ipproto_udp, // UDP protocol
. Uli_u = {. Ports =
{. Sport = 32768, // The first source port automatically selected
. Dport = 16000 }}; // destination port
Query the route table using this struct. The result is definitely the main table, and the saddr is 172.16.48.2. Obtain a struct rtable structure as the route query result.
For sockets in the my_inet domain, the struct socket has a member struct inet_sock sock representing a socket at the network layer. Its members rcv_saddr (meaning unknown) and saddr are assigned 172.16.48.2, daddr, dport is assigned to the server address and port number. The sk_state member indicating the connection status is assigned to tcp_established. Note that tcp_established is not specific to the established status of TCP connections. The status of all sockets that have successfully executed the connect operation is tcp_established. ID is assigned to the current time. The member sk_dst_cache points to the member U. dst of the rtable route query result. Thus, the socket completely caches the route query results.
When the socket after connect is executed and data reporting needs to be sent, all information about the peer end can be obtained from the socket itself. However, it should be reiterated that because of the existence of the routing cache, the efficiency of sending data packets on the connected socket is not much higher than that on the unconnected socket.