Socket remote host network communication, detailed explanation + examples! ! !

  table of Contents

1. Basic concepts

2. Principle

2.1 socket

2.2 bind

2.3 listen

2.4 accept

2.5 connect

2.6 read/recv

2.7 write/send

2.8 close 

Three, examples

Four, summary

Five, references


Network programming is a very important piece of knowledge in Linux, whether you will encounter it in work or interviews. This article will explain socket network communication with examples. Let’s start!

1. Basic concepts

A socket is usually called a socket, which is an abstraction of an endpoint for two-way communication between application processes on different hosts in the network. Sockets provide communication interfaces for upper-layer applications. See the picture below:

Figure 1 Network hierarchy                       

As can be seen from the above figure, socket is essentially an abstraction layer, encapsulating the following various protocols, and facilitating the call of upper-layer applications. 

2. Principle

Server:

1. Create a socket descriptor through the socket function;

2. Create an address and use bind to bind the address to the socket descriptor (this socket is called a listening socket);

3. Then, use listen to set the socket descriptor to listening mode and set the length of the waiting queue for connection;

4. If there is a connection, use accept to take out a connection, establish a connection with the specified client, and create a new socket for communication with the client. This socket is called a connected socket;

5. Use read/write functions to communicate with each other;

6. After all communication is completed, use the close function to close the socket;

Client:

1. Create a socket through socket;

2. Connect with the designated server through connect;

3. After the connection is successful, communicate through read/write;

4. After the communication ends, close the socket through the close function.

The communication process between different applications is as follows:

Figure 2 Socket network communication

First introduce the functions used in the figure above:

2.1 socket

int socket(int domain, int type, int protocol);

This function returns an int type socket, which is unique and can be compared with the file descriptor generated by the open function.

2.2 bind

int bind(int socket, const struct sockaddr *address, socklen_t address_len);

This function binds the address to the socket created by the socket.

2.3 listen

int listen(int sockfd, int backlog);

This function is used on the server to allow the server to receive requests from the client (other processes).

2.4 accept

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

 This function takes a connection from the queue of completed connections, and at the same time, returns a new (connected) socket, called a connected socket; the socket created by the socket is a listening socket, and a listening socket There is only one socket, and each TCP connection of the connected socket generates one.

2.5 connect

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

The client connects with the server through the connect function. If the TCP protocol is used, it is the three-way handshake process.

2.6 read/recv

ssize_t read(int fd,void *buf,size_t nbyte);
int recv(int sockfd,void *buf,int len,int flags);

 This function is responsible for reading content from fd/sockfd.

2.7 write/send

ssize_t write(int fd, const void*buf,size_t nbytes);
int send(int sockfd,void *buf,int len,int flags);

write/send write the data in buf to the file descriptor fd/sockfd.

2.8 close 

int close(int sockfd);

Close the socket.

The above function returns 0 on success, -1 on failure, and the error information is stored in errno.

Three, examples

Server code:

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PORT 3322   // 服务器端口

#define BACKLOG 1
#define MAXRECVLEN 1024

int main(int argc, char *argv[])
{
    char buf[MAXRECVLEN];
    int listenfd, connectfd;   // listendfd 监听套接字  connectfd 已连接套接字
    struct sockaddr_in server; // 服务器地址信息
    struct sockaddr_in client; // 客户端地址信息
    socklen_t addrlen;
    
    // 创建套接字描述符
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket() error. Failed to initiate a socket");
        return 0;
    }
 
    int opt = SO_REUSEADDR;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    // 将地址 server 绑定到套接字 listenfd 上
    if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
        perror("Bind() error.");
        return 0;
    }
    
    // 将套接字设置为监听模式,队列长度为 1
    if(listen(listenfd, BACKLOG) == -1) {
        perror("listen() error. \n");
        return 0;
    }

    addrlen = sizeof(client);
    while(1) {
        // 取出一个客户端请求进行连接
        if((connectfd = accept(listenfd,(struct sockaddr *)&client, &addrlen)) == -1) {
            printf("accept() error. \n");
            break;
        }

        printf("The client's ip : %s, port %d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
        
        // 与客户端通信
        char str[] = "Hello Client, I'm Server!\n";
        while(1) {
            int iret = recv(connectfd, buf, MAXRECVLEN, 0);
            if(iret > 0) {
                printf("%s\n",buf);
            } else {
                close(connectfd);
                break;
            }
            send(connectfd, str, sizeof(str), 0); 
        }
    }
    // 关闭 socket
    close(listenfd); 
    return 0;
}

Client code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 3322  //服务器端口

#define MAXDATASIZE 100

int main(int argc, char *argv[])
{
    int sockfd, num;
    char buf[MAXDATASIZE];
    struct hostent *host;
    struct sockaddr_in server;
    
    // 参数检查
    if (argc != 2) {
        printf("Usage: %s <IP Address>\n",argv[0]);
        return 0;
    }
    
    if((host = gethostbyname(argv[1])) == NULL) {
        printf("gethostbyname() error\n");
        return 0;
    }
    
    // 创建套接字
    if((sockfd = socket(AF_INET,SOCK_STREAM, 0))==-1) {
        printf("socket() error\n");
        return 0;
    }

    bzero(&server,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr = *((struct in_addr *)host->h_addr);

    // 与服务器建立连接
    if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
        printf("connect() error\n");
        return 0;
    }
    
    // 与服务器进行通信
    char str[] = "Hello Server, I'm Client!\n";
    while(true) {
        if((num = send(sockfd,str,sizeof(str),0)) == -1) {
            printf("send() error\n");
            break;
        }

        if((num = recv(sockfd,buf,MAXDATASIZE,0)) == -1) {
            printf("recv() error\n");
            break;
        }
        buf[num-1]='\0';
        printf("%s\n", buf);
        sleep(3);
    }

    // 关闭套接字
    close(sockfd);
    return 0;
}

Makefile:

all: client server

client: client.c
	gcc -o client client.c

server: server.c 
	gcc -o server server.c

clean:
	rm -rf client server

The result of compiling and running, communicating with a host:

Figure 3 Communication with the same machine

If the server and client are both locally, they can communicate using shared socket files instead of binding ports. 

Communication between different hosts:

 

Figure 4 Remote communication server
Figure 5 Remote communication client

 

Four, summary

The above is more from an application point of view to explain if network communication is carried out through sockets, there will be time to explain from a deeper perspective later.

Five, references

[1] https://www.cnblogs.com/langren1992/p/5101380.html

[2] https://blog.csdn.net/tanzongbiao/article/details/82344074

[3] https://blog.csdn.net/wjy741223284/article/details/98513237

Guess you like

Origin blog.csdn.net/u011074149/article/details/113275450