A brief analysis of socket

Socket means "socket", which is a convention for communication between computers, and can also be regarded as a technology. Through the socket convention, a computer can receive data from other computers, and can also send data to other computers.

The bottom layer in the socket is:

typedef __uint32_t  in_addr_t;  /* base type for internet address */

Then it is put into a structure called in_addr for later use.

/*
 * Internet address (a structure for historical reasons)
 */
struct in_addr {
    in_addr_t s_addr;
};

Then it is put into the structure of sockaddr_in, that is, the socket address, which is the internet method.

/*
 * Socket address, internet style.
 */
struct sockaddr_in {
    __uint8_t   sin_len;
    sa_family_t sin_family;
    in_port_t   sin_port;
    struct  in_addr sin_addr;
    char        sin_zero[8];
};

The socket address is defined again in the socket.h file, which includes its length, address family, and address value.

struct sockaddr {
    __uint8_t   sa_len;     /* total length */
    sa_family_t sa_family;  /* [XSI] address family */
    char        sa_data[14];    /* [XSI] addr value (actually larger) */
};

So let's take a look at the address family.

/*
 * Address families.
 */
#define AF_UNSPEC   0       /* unspecified */
#define AF_UNIX     1       /* local to host (pipes) */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define AF_LOCAL    AF_UNIX     /* backward compatibility */
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#define AF_INET     2       /* internetwork: UDP, TCP, etc. */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define AF_IMPLINK  3       /* arpanet imp addresses */
#define AF_PUP      4       /* pup protocols: e.g. BSP */
#define AF_CHAOS    5       /* mit CHAOS protocols */
#define AF_NS       6       /* XEROX NS protocols */
#define AF_ISO      7       /* ISO protocols */
#define AF_OSI      AF_ISO
#define AF_ECMA     8       /* European computer manufacturers */
#define AF_DATAKIT  9       /* datakit protocols */
#define AF_CCITT    10      /* CCITT protocols, X.25 etc */
#define AF_SNA      11      /* IBM SNA */
#define AF_DECnet   12      /* DECnet */
#define AF_DLI      13      /* DEC Direct data link interface */
#define AF_LAT      14      /* LAT */
#define AF_HYLINK   15      /* NSC Hyperchannel */
#define AF_APPLETALK    16      /* Apple Talk */
#define AF_ROUTE    17      /* Internal Routing Protocol */
#define AF_LINK     18      /* Link layer interface */
#define pseudo_AF_XTP   19      /* eXpress Transfer Protocol (no AF) */
#define AF_COIP     20      /* connection-oriented IP, aka ST II */
#define AF_CNT      21      /* Computer Network Technology */
#define pseudo_AF_RTIP  22      /* Help Identify RTIP packets */
#define AF_IPX      23      /* Novell Internet Protocol */
#define AF_SIP      24      /* Simple Internet Protocol */
#define pseudo_AF_PIP   25      /* Help Identify PIP packets */
/*define pseudo_AF_BLUE 26     Identify packets for Blue Box - Not used */
#define AF_NDRV     27      /* Network Driver 'raw' access */
#define AF_ISDN     28      /* Integrated Services Digital Network*/
#define AF_E164     AF_ISDN     /* CCITT E.164 recommendation */
#define pseudo_AF_KEY   29      /* Internal key-management function */
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#define AF_INET6    30      /* IPv6 */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define AF_NATM     31      /* native ATM access */
#define AF_SYSTEM   32      /* Kernel event messages */
#define AF_NETBIOS  33      /* NetBIOS */
#define AF_PPP      34      /* PPP communication protocol */
#define pseudo_AF_HDRCMPLT 35       /* Used by BPF to not rewrite headers
                     * in interface output routine */
#define AF_RESERVED_36  36      /* Reserved for internal usage */
#define AF_IEEE80211    37              /* IEEE 802.11 protocol */
#define AF_UTUN     38
#define AF_MAX      40
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */

This includes the commonly used AF_INET, including TCP, UDP and other address families.

As for the protocol family, it is currently the same as the address family.

/*
 * Protocol families, same as address families for now.
 */
#define PF_UNSPEC   AF_UNSPEC
#define PF_LOCAL    AF_LOCAL
#define PF_UNIX     PF_LOCAL    /* backward compatibility */
#define PF_INET     AF_INET
#define PF_IMPLINK  AF_IMPLINK
#define PF_PUP      AF_PUP
#define PF_CHAOS    AF_CHAOS
#define PF_NS       AF_NS
#define PF_ISO      AF_ISO
#define PF_OSI      AF_ISO
#define PF_ECMA     AF_ECMA
#define PF_DATAKIT  AF_DATAKIT
#define PF_CCITT    AF_CCITT
#define PF_SNA      AF_SNA
#define PF_DECnet   AF_DECnet
#define PF_DLI      AF_DLI
#define PF_LAT      AF_LAT
#define PF_HYLINK   AF_HYLINK
#define PF_APPLETALK    AF_APPLETALK
#define PF_ROUTE    AF_ROUTE
#define PF_LINK     AF_LINK
#define PF_XTP      pseudo_AF_XTP   /* really just proto family, no AF */
#define PF_COIP     AF_COIP
#define PF_CNT      AF_CNT
#define PF_SIP      AF_SIP
#define PF_IPX      AF_IPX      /* same format as AF_NS */
#define PF_RTIP     pseudo_AF_RTIP  /* same format as AF_INET */
#define PF_PIP      pseudo_AF_PIP
#define PF_NDRV     AF_NDRV
#define PF_ISDN     AF_ISDN
#define PF_KEY      pseudo_AF_KEY
#define PF_INET6    AF_INET6
#define PF_NATM     AF_NATM
#define PF_SYSTEM   AF_SYSTEM
#define PF_NETBIOS  AF_NETBIOS
#define PF_PPP      AF_PPP
#define PF_RESERVED_36  AF_RESERVED_36
#define PF_UTUN     AF_UTUN
#define PF_MAX      AF_MAX

The following are the types of Socket, the most common are sock_stream and sock_dgram, which are the data transmission methods of TCP and UDP respectively

/*
 * Types
 */
#define SOCK_STREAM 1       /* stream socket */
#define SOCK_DGRAM  2       /* datagram socket */
#define SOCK_RAW    3       /* raw-protocol interface */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define SOCK_RDM    4       /* reliably-delivered message */
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#define SOCK_SEQPACKET  5       /* sequenced packet stream */
  • SOCK_STREAM
    represents a connection-oriented data transfer method. Data arrives at another computer without error, and can be resent if damaged or lost, but relatively slowly. The common http protocol uses SOCK_STREAM to transmit data, because it is necessary to ensure the correctness of the data, otherwise the web page cannot be parsed normally.

  • SOCK_DGRAM
    represents a connectionless data transfer method. The computer only transmits the data without checking the data. If the data is damaged during transmission, or does not reach another computer, there is no way to remedy it. That is to say, if the data is wrong, it is wrong and cannot be retransmitted. Because SOCK_DGRAM does less verification work, it is more efficient than SOCK_STREAM.


The difference between TCP and UDP is as follows:
TCP is connection-oriented. The processes on both sides of the interaction each establish a stream socket, and the server needs to wait for the client to submit a connection application to it. A new socket descriptor is returned as soon as the client request is accepted. The data transfer function is called through the descriptor to send and receive data with the client.

UDP is connectionless. The two sides establish a datagram socket. The server and client do not need to apply for and establish a connection before transmitting data, and can send messages to each other at any time.

protocol TCP UDP
data transmission method streaming Datagram
advantage reliable and stable Faster and slightly more secure than TCP
shortcoming Slow speed, low efficiency, high system resource occupation, easy to be attacked unreliable, unstable
suitable for the scene High requirements for network communication quality (reliable and stable) The quality of network communication is not high and the speed is fast.

It is necessary to distinguish the difference between protocols, services and ports:
services generally correspond to ports, for example, Web services correspond to port 80, FTP services correspond to port 21, and SMTP services correspond to port
25. Protocols refer to protocols such as TCP. The protocol is used in the service. For example, the FTP protocol is used in FTP.

Here is the code on the server side:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <zconf.h>

int UDP()
{
    int server_sockfd;
    ssize_t len;
    struct sockaddr_in my_addr;   //服务器网络地址结构体
    struct sockaddr_in remote_addr; //客户端网络地址结构体
    socklen_t sin_size;
    char buf[BUFSIZ];  //数据传送的缓冲区
    memset(&my_addr, 0, sizeof(my_addr)); //数据初始化--清零
    my_addr.sin_family = AF_INET; //设置为IP通信
    my_addr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
    my_addr.sin_port = htons(8000); //服务器端口号

    /*创建服务器端套接字--IPv4协议,面向无连接通信,UDP协议*/
    if((server_sockfd = socket(PF_INET, SOCK_DGRAM, 0))<0)
    {
        perror("socket error");
        return 1;
    }

    /*将套接字绑定到服务器的网络地址上*/
    if (bind(server_sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("bind error");
        return 1;
    }

    printf("my address %s\n", inet_ntoa(my_addr.sin_addr));
    sin_size = sizeof(struct sockaddr_in);
    printf("waiting for a packet...\n");

    /*接收客户端的数据并将其发送给客户端--recvfrom是无连接的*/
    if((len = recvfrom(server_sockfd, buf, BUFSIZ, 0, (struct sockaddr *)&remote_addr, &sin_size)) < 0)
    {
        perror("recvfrom error");
        return 1;
    }
    printf("received packet from %s:\n", inet_ntoa(remote_addr.sin_addr));
    buf[len] = '\0';
    printf("contents: %s\n", buf);

    /*关闭套接字*/
    close(server_sockfd);

    return 0;
}

int TCP()
{
    int server_sockfd;//服务器端套接字
    int client_sockfd;//客户端套接字
    ssize_t len;
    struct sockaddr_in my_addr;   //服务器网络地址结构体
    struct sockaddr_in remote_addr; //客户端网络地址结构体
    socklen_t sin_size;
    char buf[BUFSIZ];  //数据传送的缓冲区
    memset(&my_addr, 0, sizeof(my_addr)); //数据初始化--清零
    my_addr.sin_family = AF_INET; //设置为IP通信
    my_addr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
    my_addr.sin_port = htons(8000); //服务器端口号

    /*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/
    if((server_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error");
        return 1;
    }

    /*将套接字绑定到服务器的网络地址上*/
    if(bind(server_sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("bind error");
        return 1;
    }

    printf("my address %s\n", inet_ntoa(my_addr.sin_addr));

    /*监听连接请求--监听队列长度为5*/
    if(listen(server_sockfd, 5) < 0)
    {
        perror("listen error");
        return 1;
    };

    sin_size = sizeof(struct sockaddr_in);

    /*等待客户端连接请求到达*/
    if((client_sockfd = accept(server_sockfd, (struct sockaddr *)&remote_addr, &sin_size))<0)
    {
        perror("accept error");
        return 1;
    }
    printf("accept client %s\n", inet_ntoa(remote_addr.sin_addr));
    len = send(client_sockfd, "Welcome to my server\n", 21, 0);//发送欢迎信息

    /*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/
    while((len = recv(client_sockfd, buf, BUFSIZ, 0)) > 0)
    {
        buf[len] = '\0';
        printf("%s\n", buf);
        if(send(client_sockfd, buf, len, 0) < 0)
        {
            perror("write error");
            return 1;
        }
    }

    /*关闭套接字*/
    close(client_sockfd);
    close(server_sockfd);

    return 0;
}

int main(int argc, char *argv[])
{
    UDP();
    return 0;
}

Here is the code for the client:

#include <cstdio>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <zconf.h>

int UDP()
{
    int client_sockfd;
    ssize_t len;
    struct sockaddr_in remote_addr; //服务器端网络地址结构体
    socklen_t sin_size;
    char buf[BUFSIZ];  //数据传送的缓冲区
    memset(&remote_addr, 0, sizeof(remote_addr)); //数据初始化--清零
    remote_addr.sin_family = AF_INET; //设置为IP通信
    remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器IP地址
    remote_addr.sin_port = htons(8000); //服务器端口号

    /*创建客户端套接字--IPv4协议,面向无连接通信,UDP协议*/
    if((client_sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error");
        return 1;
    }
    strcpy(buf,"This is a test message!"); // 发送的内容
    printf("sending: '%s'\n",buf);
    sin_size = sizeof(struct sockaddr_in);

    /*向服务器发送数据包*/
    if((len = sendto(client_sockfd, buf, strlen(buf), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))) < 0)
    {
        perror("recvfrom");
        return 1;
    }

    /*关闭套接字*/
    close(client_sockfd);

    return 0;
}

int TCP()
{
    int client_sockfd;
    ssize_t len;
    struct sockaddr_in remote_addr; //服务器端网络地址结构体
    char buf[BUFSIZ];  //数据传送的缓冲区
    memset(&remote_addr, 0, sizeof(remote_addr)); //数据初始化--清零
    remote_addr.sin_family = AF_INET; //设置为IP通信
    remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器IP地址
    remote_addr.sin_port = htons(8000); //服务器端口号

    /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/
    if((client_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error");
        return 1;
    }

    /*将套接字绑定到服务器的网络地址上*/
    if(connect(client_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("Connect error");
        return 1;
    }
    printf("connected to server\n");
    len = recv(client_sockfd, buf, BUFSIZ, 0);//接收服务器端信息
    buf[len] = '\0';
    printf("%s", buf); //打印服务器端信息

    /*循环的发送接收信息并打印接收信息(可以按需发送)--recv返回接收到的字节数,send返回发送的字节数*/
    while(1)
    {
        printf("Enter string to send:");
        scanf("%s", buf);
        if(!strcmp(buf, "quit"))
            break;
        len = send(client_sockfd, buf, strlen(buf), 0);
        len = recv(client_sockfd, buf, BUFSIZ, 0);
        buf[len] = '\0';
        printf("received:%s\n", buf);
    }

    /*关闭套接字*/
    close(client_sockfd);

    return 0;
}

int main(int argc, char *argv[]){
    UDP();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325652155&siteId=291194637