C中的TCP连接:插座编程指南
#算法 #c #networking

我们都知道编程语言和框架正在以惊人的速度增长。学习构建网络连接的C程序似乎无关紧要。但是,等等,为什么我们不深入研究编程的黄金时代,并构建一些简单的程序来激发我们对精通技术设置的不足工作的兴趣?

我的想法很简单;我只想介绍一个简短的代码段,它显示了如何在C 中建立TCP或UDP连接并传输数据。

内容

  1. 设置服务器
  2. 设置客户端
  3. 运行服务器和客户端可执行文件
  4. 其他设置

1.设置服务器

  • 声明clientserver结构变量和其他必要变量:

    struct sockaddr_in client, server;
    int lfd, n, confd;
    char r_buff[100] = "", s_buff[100] = "";
    
  • 使用socket()创建一个TCP套接字,并将值分配给server结构:

    lfd = socket(AF_INET, SOCK_STREAM, 0);
    server.sin_family = AF_INET;
    server.sin_port = 2000;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    

    这里AF_INET是地址家族,SOCK_STREAM是类型,0用于默认协议。

  • 使用bind()将套接字与地址和服务器结构绑定,并使用listen()
    收听连接

    bind(lfd, (struct sockaddr *)&server, sizeof server);
    listen(lfd, 1);
    
  • 使用accept()接受客户的连接:

    n = sizeof client;
    confd = accept(lfd, (struct sockaddr *)&client, &n);
    
  • 使用recv()从客户端接收消息:

    recv(confd, r_buff, sizeof r_buff, 0);
    printf("\n[client] %s", r_buff);
    
  • 使用send()将消息发送回客户端

    printf("\nserver: ");
    gets(s_buff);
    send(confd, s_buff, sizeof s_buff, 0);
    
  • 使用close()停止插座和结束连接

    close(confd);
    close(lfd);
    
  • server.c的最终代码

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    int main() {
        struct sockaddr_in client, server;
        int lfd, n, confd;
        char r_buff[100] = "", s_buff[100] = "";
    
        lfd = socket(AF_INET, SOCK_STREAM, 0);
        server.sin_family = AF_INET;
        server.sin_port = 2000;
        server.sin_addr.s_addr = inet_addr("127.0.0.1");
    
        bind(lfd, (struct sockaddr *)&server, sizeof server);
        listen(lfd, 1);
    
        n = sizeof client;
        confd = accept(lfd, (struct sockaddr *)&client, &n);
    
        while (1) {
            recv(confd, r_buff, sizeof r_buff, 0);
            printf("\n[client] %s", r_buff);
            if (strcmp(r_buff, "exit") == 0)
                break;
    
            printf("\nserver: ");
            gets(s_buff);
            send(confd, s_buff, sizeof s_buff, 0);
            if (strcmp(s_buff, "exit") == 0)
                break;
            printf("\n");
        }
    
        close(confd);
        close(lfd);
    
        return 0;
    }
    

2.设置客户端

  • 声明server结构变量和坏死变量:

    struct sockaddr_in server;
    int lfd;
    char r_buff[100] = "", s_buff[100] = "";
    
  • 使用socket()创建一个TCP套接字,并将值分配给server结构:

    lfd = socket(AF_INET, SOCK_STREAM, 0);
    server.sin_family = AF_INET;
    server.sin_port = 2000;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    
  • 使用connect()连接到服务器:

    connect(lfd, (struct sockaddr *)&server, sizeof server);
    
  • 使用send()将消息发送到服务器:

    printf("\nclient: ");
    gets(s_buff);
    send(lfd, s_buff, sizeof s_buff, 0);
    
  • 使用recv()接收从服务器接收邮件:

    recv(lfd, r_buff, sizeof r_buff, 0);
    printf("[server] %s", r_buff);
    
  • 使用close()停止插座和结束连接

    close(lfd);
    
  • client.c的最终代码

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    int main() {
    struct sockaddr_in server;
    int lfd;
    char r_buff[100] = "", s_buff[100] = "";
    
    lfd = socket(AF_INET, SOCK_STREAM, 0);
    server.sin_family = AF_INET;
    server.sin_port = 2000;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    connect(lfd, (struct sockaddr *)&server, sizeof server);
    
    while (1) {
        printf("\nclient: ");
        gets(s_buff);
        send(lfd, s_buff, sizeof s_buff, 0);
        if (strcmp(s_buff, "end") == 0)
        break;
    
        recv(lfd, r_buff, sizeof r_buff, 0);
        printf("[server] %s", r_buff);
        if (strcmp(r_buff, "end") == 0)
        break;
    
        printf("\n");
    }
    
    close(lfd);
    
    return 0;
    }
    

注意:system calls socket()bind()listen()connect()accept()accept()send()recv()recv()在上述程序中是从库中导入的,这些库仅可能仅在Linux Distributions(OS)中运行,;显然,这些程序不能在其他操作系统中执行,例如 windows


3.运行服务器和客户端可执行文件

  • 编译服务器和客户端代码

    gcc server.c -o server.out
    gcc client.c -o client.out
    
  • 执行服务器和客户端(在相应的 order 中)

    # in terminal-1 or system-1
    ./server.out
    
    # in terminal-2 or system-2
    ./client.out
    

确保在不同的终端中执行它们
(或不同的系统,如果您被分配了公共IP地址)

  • 如果一切都很好,您可以期待这样的东西。

    • 客户端

      client

    • 服务器

      server


4.其他设置

  • 记录请求到文件

    • 编辑server.c并添加,

      FILE *fp;
      fp = fopen("log.txt", "a");
      
      fputs(r_buff, fp);
      fputs("\t", fp);
      fputs(s_buff, fp);
      fputs("\n", fp);
      fclose(fp);
      

      确保不仅使用fputs()在循环中;在这种情况下,您可能需要在开始和结束时分别在循环主体内使用fopen()fclose()

  • 您可以尝试添加诸如 Prime Checker palindrome Checker 等的功能,以使此程序更有用