1

Client/Server Programming Pattern

  • The server remains on the network for a long time (disclosing its own IP address) and waits for the client to connect
  • The client initiates a connection action and waits for the server to respond
  • Features:

    • The server cannot actively connect to the client
    • The client can only connect to the server in a predefined way (protocol)

server-side programming

 1. 准备网络连接
2. 绑定端口
3. 进入端口监听状态
4. 等待连接

image.png

The core work of the server: binding & listening & receiving

  • Binding: int bind(int sock, struct sockaddr *addr, socklen_t addrlen);
  • Monitor: int listen(int sock, int backlog);
  • Receive: int accept(int sock, struct sockaddr *addr, socklen_t addrlen);

In-depth analysis of the server

  • The server socket is only used for receiving connections, not for actual communication
  • When a connection is received, the accept() function returns the socket to communicate with the client
  • Server socket generates client socket for communication
So, what exactly is a socket? How to understand?

Deep understanding of socket() function

  • what is socket()?

    • socket() is a multifunctional function
  • What does socket() return?

    • The return value of socket() is the resource identifier used for communication
  • What else can socket() do?

    • socket() can provide different types of communication functions (local inter-process communication)

Programming experiment: first experience of server-side programming

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

int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int clinet = 0;
    struct sockaddr_in caddr = {0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = {0};
    int r = 0;

    server = socket(PF_INET, SOCK_STREAM, 0);

    if (server == -1) {
        printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8899);

    if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
        printf("server bind error\n");
        return -1;
    }

    if (listen(server, 1) == -1) {
        printf("server listen error\n");
        return -1;
    }

    printf("server start success\n");

    asize = sizeof(caddr);

    clinet = accept(server, (struct sockaddr*)&caddr, &asize);

    if (clinet == -1) {
        printf("client accept error\n");
        return -1;
    }

    printf("client: %d\n", clinet);

    len = 0;

    do {
        int i = 0;
        
        r = recv(clinet, buf, sizeof(buf), 0);

        if (r > 0) {
            len += r;
        }

        for (i=0; i<r; ++i) {
            printf("%c", buf[i]);
        }
    } while (len < 64);

    printf("\n");

    send(clinet, "hello word!", 12, 0);

    sleep(1);

    close(clinet);
    close(server);

    return 0;
}
INADDR_ANY => "0.0.0.0" , indicating that all connections of the machine are accepted (for example, when the machine has multiple network cards and then has multiple IPs)

Core Patterns of Client/Server Programming

  • The server runs for a long time (infinite loop) to receive the client's request
  • After the client connects, it sends a request (protocol data) to the server

image.png

Server-side core programming model

image.png

Programming Experiment: Client/Server Programming Experiment

  1. The server continuously listens for client connections
  2. echo client data after the server is connected
  3. The server disconnects after receiving quit
  4. The client receives user input and sends it to the server
Server
 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int client = 0;
    struct sockaddr_in caddr = {0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = {0};
    int r = 0;

    server = socket(PF_INET, SOCK_STREAM, 0);

    if (server == -1) {
        printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8888);

    if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
        printf("server bind error\n");
        return -1;
    }

    if (listen(server, 1) == -1) {
        printf("server listen error\n");
        return -1;
    }

    printf("server start success\n");

    while (1) {
        asize = sizeof(caddr);

        client = accept(server, (struct sockaddr*)&caddr, &asize);

        if (client == -1) {
            printf("client accept error\n");
            return -1;
        }

        printf("client: %d\n", client);

        do {
            r = recv(client, buf, sizeof(buf), 0);
            if (r > 0) {
                printf("Receive: %s\n", buf);

                if (strcmp(buf, "quit") != 0) {
                    len = send(client, buf, r, 0);
                }
                else {
                    break;
                }
            } 
        } while (r > 0);

        close(client);
    }

    close(server);

    return 0;
}
client
 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int sock = 0;
    struct sockaddr_in addr = {0};
    int len = 0;
    char buf[128] = {0};
    char input[32] = {0};
    int r = 0;

    sock = socket(PF_INET, SOCK_STREAM, 0);

    if (sock == -1) {
        printf("socket error\n");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("192.168.2.46");
    addr.sin_port = htons(8888);

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        printf("connect error\n");
        return -1;
    }

    printf("connect success\n");

    while (1) {
        printf("Input: ");

        scanf("%s", input);

        len = send(sock, input, strlen(input) + 1, 0);

        r = recv(sock, buf, sizeof(buf), 0);

        if (r > 0) {
            printf("Receive: %s\n", buf);
        }
        else {
            break;
        }
    }

    close(sock);

    return 0;
}
Thinking: How to enhance the capabilities of the server and support multiple clients at the same time?

TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧