Realize the principle of

The realization principle is very simple, write a simple TCP server, its client processing mode using threading processing. One of the issues to be noted is multi-threaded concurrency.

The multithreaded client passes the CONNECt_sockFD to the thread and lets the thread process it.

TCP server

The brief steps

  1. Create a socket.
  2. Configure address data.
  3. Socket binding address.
  4. Listening in. (listen ())
  5. Enter the loop processing.
    1. Accept () gets a connect_socket for the incoming client.
    2. Create a thread dedicated to processing the link and pass the Connect_socket to the thread.

Pay attention to

Note:

  1. The value of the CONNECt_socket is passed to the client processing thread. Pay attention to the transfer technique and the system bit of the running device.
  2. This program uses a global atomic integer to maintain the client connection number.
  3. #include “atomic_lzm.h” is a personal implementation of the Linux application layer’s atomic library, which is simply wrapped, using the POSIX muexes API. If you need it, just go get it from my Gitee.

TCP client

The brief steps

  1. Create a socket.
  2. Configure address data.
  3. Establishing a TCP connection.
  4. After the connection is successful, data interaction is started.

Pay attention to

Note:

  1. Note the IP address and port number of the server.

The experimental results

Need to test the client limit can open a few more clients. If you are interested, you can verify it for yourself.

Reference source

Server side reference source code

/** @file server.c * @brief * @details * @author LZM * @date 2021-06-10 16:49:46 * @version v1.0 * @copyright Copyright By lizhuming, All Rights Reserved * @blog https://www.cnblogs.com/lizhuming/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @ the LOG change LOG: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>
#include "atomic_lzm.h"

// Note: if the receive buffer is smaller than or equal to the send buffer of the receiver, the receiver will not receive multiple times.

#define CLIENT_BUFF_MAX 1024 // The client receives buffer size
#define MY_SERVER_PORT 8080 // The server listens on the port
#define CLIENT_PENDING_NUM 10 // The number of client buffers for kernel incomplete queues
#define CLIENT_MAX_NUM 2 // Client connection limit

// Define an unnamed semaphore
//sem_t sem_client;

atomic_lzm_t g_client_num;

/** * @name client_fun * @brief thread function, handling client * @param arg: resource * @retval * @author LZM */
void *client_fun(void *arg)
{
    int recv_len = 0; // Receive length
    char recv_buff[CLIENT_BUFF_MAX] = "";
    long connfd = (long)arg; // The socket is connected. Value passing (note the concurrency of multiple threads when passing addresses)

    // [1] Receive data
    while((recv_len = recv(connfd, recv_buff, sizeof(recv_buff), 0)) > 0)
    {
        printf("[%ld]recv_buff:%s\r\n", connfd, recv_buff); // Prints data
        send(connfd, "OK".2.0); / / back to the client
    }

    // [2] Closes the socket
    printf("client closed! \r\n");
    close(connfd); / / close the socket
    //sem_post(&sem_client);
    atomic_lzm_sub(&g_client_num);
    printf("can link num is [%d]\n", CLIENT_MAX_NUM-atomic_lzm_get(&g_client_num));
    return NULL;
}

/** * @name main * @brief main * @param * @retval * @author LZM */
int main(int argc, char *argv[])
{
    int sockfd = 0; / / listening socket
    long connfd = 0; // The socket is connected. Long avoids errors with 64-bit machines
    int ret = 0; // return buffer
    struct sockaddr_in local_server_addr; // Address of the local server
    unsigned short local_server_port = MY_SERVER_PORT; // The local server listens on the port
    pthread_t thread_client_id; // Id of the client thread

    atomic_lzm_init(&g_client_num, 0);

    printf("TCP server started at port [%d]! \n", local_server_port);

    // [1] Create a socket
    printf("create server socket! \n");
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        printf("%s-%s-%d:sockfd create faild!", __FILE__, __FUNCTION__, __LINE__);
        perror("socket create error");
        exit(- 1);
    }

    // [2] Initializes address data
    printf("init server address! \n");
    bzero(&local_server_addr, sizeof(local_server_addr)); // Initialize the server address
    local_server_addr.sin_family = AF_INET;
    local_server_addr.sin_port = htons(local_server_port);
    local_server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    / / [3] binding
    printf("bing server socket and addr! \n");
    ret = bind(sockfd, (struct sockaddr*)&local_server_addr, sizeof(local_server_addr));
    if(ret ! =0)
    {
        printf("%s-%s-%d:sockfd bind faild!", __FILE__, __FUNCTION__, __LINE__);
        perror("socket bind error");
        close(sockfd);
        exit(- 1);
    }

    / / [4] to monitor
    printf("listen server socket! \n");
    ret = listen(sockfd, CLIENT_PENDING_NUM);
    if(ret ! =0)
    {
        printf("%s-%s-%d:sockfd listen faild!", __FILE__, __FUNCTION__, __LINE__);
        perror("socket listen error");
        close(sockfd);
        exit(- 1);
    }

    //sem_init(&sem_client, 0, CLIENT_MAX_NUM);

    printf("accept! \n");

    // [5] Process client
    while(1)
    {
        char client_ip[INET_ADDRSTRLEN] = ""; // use for save client ip
        struct sockaddr_in client_addr; // use for save client address
        socklen_t client_len = sizeof(client_addr); // Must be initialized

        //sem_wait(&sem_client);

        // [5][1] Gets an established connection
        connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
        if(connfd < 0)
        {
            printf("%s-%s-%d:sockfd accept faild!", __FILE__, __FUNCTION__, __LINE__);
            perror("accept error");
            continue;
        }

        if(atomic_lzm_get(&g_client_num) >= CLIENT_MAX_NUM)
        {
            close(connfd);
        }
        else
        {
            // [5][2] Process client data
            inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
            printf("clien ip = [%s], port = [%d]\n", client_ip, ntohs(client_addr.sin_port));

            if(connfd > 0)
            {
                // The thread processes client data
                pthread_create(&thread_client_id, NULL, (void *)client_fun, (void *)connfd); / / creat thread. Note that the 64-bit machine address is 8byte
                pthread_detach(thread_client_id); // Thread separation. In real time, the thread resource is automatically reclaimed when the thread callback function endsatomic_lzm_add(&g_client_num); }}printf("can link num is [%d]\n", CLIENT_MAX_NUM-atomic_lzm_get(&g_client_num));
    }

    // [6] Disable the server socket
    close(sockfd);

    return 0;
}
Copy the code

TCP client source

/** @file client. C * @brief * @details * @author LZM * @date 2021-06-10 09:49:46 * @version v1.0 * @copyright Copyright By lizhuming, All Rights Reserved * @blog https://www.cnblogs.com/lizhuming/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @ the LOG change LOG: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>

#define sHOST "192.168.112.128" // Server IP address
#define sPORT 8080                  // Server process port number

#define BUFFER_SIZE (1*1024)   // Data field size

// Note: if the receive buffer is smaller than or equal to the send buffer of the receiver, the receiver will not receive multiple times.


/** * @brief Read thread * @param * @retval * @author */
void *client_read_fun(void *arg) 
{
    int recv_len = 0; // Receive length
    char recv_buff[BUFFER_SIZE] = "";
    int sockfd = *(int *)arg; // Connected socket

    while((recv_len = recv(sockfd, recv_buff, sizeof(recv_buff), 0)) > 0)
    {
        printf("[%d]recv_buff:%s\r\n", sockfd, recv_buff);
    }

    printf("exit read thread!");
    return NULL;
}

/** * @brief main function * @param * @retval * @author */
int main(void)
{
    int sockfd; // Socket descriptor
    int ret;    // Return the result
    struct sockaddr_in server; // Socket address
    char data_buffer[BUFFER_SIZE];  // app data field
    pthread_t thread_read_id; // Read thread ID

    /* [1] Create a socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == - 1)
    {
        printf("creat socket failed! \n");
        exit(1);
    }

    /* [2] Initialize the address */
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(sPORT);
    server.sin_addr.s_addr = inet_addr(sHOST);

    /* [3] Establish a TCP connection */
    ret = connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr));
    if(ret == - 1)
    {
        printf("connect server failed! \n");
        close(sockfd);
        exit(1);
    }

    printf("connect server success!");

    /* [4][1] Create a reader thread */
    //pthread_create(&thread_read_id, NULL, (void *)client_read_fun, (void *)&(sockfd));
    //pthread_detach(thread_read_id); // Thread separation

    /* [4][2] enter a loop to write */
    while(1)
    {
        printf("please enter some text:");
        fgets(data_buffer, BUFFER_SIZE, stdin);

        // Type end to exit the loop
        if(strncmp(data_buffer, "end".3) = =0)
            break;

        send(sockfd, data_buffer, sizeof(data_buffer), 0);

        bzero(data_buffer, sizeof(data_buffer));

        recv(sockfd, data_buffer, sizeof(data_buffer), 0);

        printf("data_buff:%s\r\n", data_buffer);

    }

    /* [5] Exit */
    close(sockfd);
    exit(0);
}
Copy the code

The latest 2021 collection of some high frequency interview questions (are organized into a document), there are a lot of dry things, including mysql, Netty, Spring, threads, Spring Cloud, JVM, source code, algorithm, etc., there are also detailed learning planning map, interview questions organized, etc