使用C语言编写基于TCP协议的Socket通讯程序实例分享

本篇文章的主要目标是向大家分享如何使用C语言编写基于TCP协议的Socket通讯程序。这个过程分为以下几个步骤:

步骤一:创建Socket

首先,我们需要创建一个Socket。Socket是一个用于数据传输的端点,可以理解为建立数据传输通道的道具。在C语言中,我们可以使用socket()函数创建Socket。具体代码如下:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

这里,我们创建了一个IPv4的TCP Socket。AF_INET表示IPv4协议,SOCK_STREAM表示TCP协议。如果你想使用UDP协议,则需要将SOCK_STREAM改为SOCK_DGRAM

步骤二:设置Socket选项

有些特定的操作系统需要手动地启用某些功能才能使用Socket通信。在这种情况下,我们就需要使用setsockopt()函数设置Socket选项。例如,在Linux系统中,我们需要设置SO_REUSEADDR选项以允许多个进程绑定到相同的端口。具体代码如下:

int enable = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));

这里,我们将SO_REUSEADDR选项启用,并将其设置为1。

步骤三:绑定Socket到本地IP和端口

在进行数据传输前,我们需要将创建的Socket绑定到一个本地IP地址和端口。这可以通过bind()函数来完成。具体代码如下:

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));

这里,我们将Socket绑定到本地IP地址INADDR_ANY,并将端口号port转换成网络字节序,然后将其存储在addr.sin_port中。

步骤四:监听连接请求

完成了Socket的绑定,我们还需要通过listen()函数告诉系统我们打算接受传入的连接请求。具体代码如下:

listen(sockfd, backlog);

这里,backlog参数表示系统在连接队列中排队的最大连接数。如果有更多的客户端尝试连接服务器,它们将被拒绝,直到当前的连接请求被处理。

步骤五:接受连接请求

现在,我们已经准备好接受客户端的连接请求了。当我们接受一个请求时,我们需要创建另一个Socket来处理该连接。具体代码如下:

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int new_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);

这里,accept()函数将等待客户端连接并返回一个新的Socket文件描述符new_sockfd。我们还可以通过client_addr参数获取客户端的IP地址和端口号。

步骤六:发送和接收数据

现在,我们已经成功地建立了一个基于TCP协议的Socket连接。我们可以使用send()函数来发送数据,使用recv()函数来接收数据。具体代码如下:

char buffer[1024];
int n = recv(new_sockfd, buffer, sizeof(buffer), 0);
buffer[n] = '\0';
printf("Received: %s\n", buffer);

const char* message = "Hello, client!";
send(new_sockfd, message, strlen(message), 0);

这里,我们使用recv()函数接收客户端发送的消息,并将其存储在名为buffer的字符数组中。然后,我们将其打印到控制台上。接着,我们使用send()函数向客户端发送一条消息。

示例一:简单的Echo服务器

下面是一个基本的Echo服务器示例,它将收到的消息返回给客户端:

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

int main(int argc, char *argv[]) {
    int port = atoi(argv[1]);

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Cannot create socket");
        return EXIT_FAILURE;
    }

    int enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
        perror("Cannot set socket options");
        return EXIT_FAILURE;
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("Cannot bind socket");
        return EXIT_FAILURE;
    }

    if (listen(sockfd, 5) < 0) {
        perror("Cannot listen socket");
        return EXIT_FAILURE;
    }

    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int new_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
        if (new_sockfd < 0) {
            perror("Cannot accept socket");
            continue;
        }

        char buffer[1024];
        int n = recv(new_sockfd, buffer, sizeof(buffer), 0);
        if (n <= 0) {
            close(new_sockfd);
            continue;
        }

        buffer[n] = '\0';
        printf("Received: %s\n", buffer);

        if (send(new_sockfd, buffer, strlen(buffer), 0) < 0) {
            perror("Cannot send socket");
        }

        close(new_sockfd);
    }

    close(sockfd);
    return EXIT_SUCCESS;
}

示例二:多线程Echo服务器

接下来,让我们实现一个多线程的Echo服务器。该服务器能够同时处理多个客户端请求。我们可以为每个客户端请求创建一个新线程,并在该线程中处理客户端请求。具体代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

void* handle_client(void* arg) {
    int sockfd = *(int*)arg;

    char buffer[1024];
    int n = recv(sockfd, buffer, sizeof(buffer), 0);
    if (n <= 0) {
        close(sockfd);
        return NULL;
    }

    buffer[n] = '\0';
    printf("Received: %s\n", buffer);

    if (send(sockfd, buffer, strlen(buffer), 0) < 0) {
        perror("Cannot send socket");
    }

    close(sockfd);

    return NULL;
}

int main(int argc, char *argv[]) {
    int port = atoi(argv[1]);

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Cannot create socket");
        return EXIT_FAILURE;
    }

    int enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
        perror("Cannot set socket options");
        return EXIT_FAILURE;
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("Cannot bind socket");
        return EXIT_FAILURE;
    }

    if (listen(sockfd, 5) < 0) {
        perror("Cannot listen socket");
        return EXIT_FAILURE;
    }

    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int new_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
        if (new_sockfd < 0) {
            perror("Cannot accept socket");
            continue;
        }

        pthread_t tid;
        if (pthread_create(&tid, NULL, handle_client, &new_sockfd) != 0) {
            perror("Cannot create thread");
            close(new_sockfd);
        }
    }

    close(sockfd);
    return EXIT_SUCCESS;
}

在这个示例中,我们创建了一个名为handle_client的线程函数。当我们接受到客户端请求时,我们创建一个新线程,并将新Socket的文件描述符传递给该线程。然后,我们在该线程中处理该连接。通过这种方式,服务器可以同时处理多个客户端请求。

以上是关于使用C语言编写基于TCP协议的Socket通讯程序实例分享的完整攻略,希望能对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用C语言编写基于TCP协议的Socket通讯程序实例分享 - Python技术站

(0)
上一篇 2023年5月24日
下一篇 2023年5月24日

相关文章

  • 解析C++中指向对象的指针使用

    当我们需要使用C++中的指针来对一个对象进行操作时,需要使用指向对象的指针。 以下是可以用来解析C++中指向对象的指针使用的攻略: 1. 创建指向对象的指针 指向对象的指针是一个存储对象地址的变量,指针变量具有自己的地址和类型,它可以为一个类的实例分配并且可以通过调用类成员函数来操作对象。 指向对象的指针有时候被称为“该对象的指针”。通常,创建指向对象的指针…

    C 2023年5月22日
    00
  • QT获取显示当前时间和日期的方法(用QTime,QDate和QDateTime)

    获取当前时间和日期是Qt中常用的操作之一,通过使用QTime、QDate和QDateTime类,可以方便地实现这个功能。下面是获取当前时间和日期的详细攻略。 使用QTime获取当前时间 要使用QTime获取当前时间,可以使用QTime::currentTime()方法获取当前系统时间的QTime对象。示例代码如下: #include <QTime&gt…

    C 2023年5月22日
    00
  • C++中的对象指针总结

    C++中的对象指针总结 在C++中,指针是非常常见的数据类型,而对象指针就是指向一个对象的指针。本文将讲解C++中的对象指针的使用以及注意事项。 声明对象指针 在C++中声明一个对象指针非常简单,如下所示: ClassName *pObject; 其中,ClassName是要指向的对象的类名,pObject是指向这个对象的指针。需要注意的是,指针声明时必须要…

    C 2023年5月22日
    00
  • C++文件读写操作详解

    先简单介绍一下C++中文件读写操作的基本概念: C++文件读写操作是指在C++程序中对计算机中的文件进行输入和输出的操作。文件读写操作是必不可少的C++编程操作之一,在文件读写操作中我们需要用到文件指针,读写位置指针,并且需要了解文件的打开、关闭、读写、复制等基本操作。C++文件操作通常使用C++标准库中的fstream头文件实现。下面介绍一些基本操作和示例…

    C 2023年5月22日
    00
  • js 转json格式的字符串为对象或数组(前后台)的方法

    要将 JS 转成 JSON 格式的字符串为对象或数组,有两种常见的方法,分别是: 1.使用 JSON.parse() 将 JSON 字符串转换为对象或数组; 2.使用 eval() 函数将 JSON 字符串转换为对象或数组。 下面我们分别来讲解这两种方法的使用方法及示例说明。 1.使用 JSON.parse() 转换成对象或数组JSON.parse() 方法…

    C 2023年5月23日
    00
  • MySQL中json字段的操作方法

    当MySQL版本大于等于5.7.8时,支持json类型的字段。json是具有可读性和结构的数据格式,MySQL提供了方便的函数和操作符来处理json数据。下面将详细讲解MySQL中json字段的操作方法。 创建json类型的字段 在MySQL中创建json类型的字段,可以使用以下语法: CREATE TABLE table_name ( id INT PRI…

    C 2023年5月23日
    00
  • php json转换成数组形式代码分享

    当我们在开发过程中需要将json格式的数据转换成数组的形式,可以使用PHP中提供的json_decode()函数。下面,我来详细讲解如何将json格式的数据转换成数组,并分享两个示例。 1. 将json转换成数组 使用方法: mixed json_decode(string $json, bool $assoc = false, int $depth = 5…

    C 2023年5月23日
    00
  • c++实现MD5算法实现代码

    实现MD5算法的代码可以分成以下几个步骤: 将数据填充到512位的块中(padding it),满足mod 512 = 448。 将数据块分成16个32位的字,每个字称为W。 初始化4个32位寄存器A、B、C、D,用于存储最终的结果。 对每一个数据块进行四轮的处理,每轮处理16次,通过位运算来更新结果寄存器。 所有数据块处理完后,将A、B、C、D四个寄存器按…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部