C语言中如何进行网络编程?

C语言中进行网络编程的步骤大致如下:

  1. 创建socket
  2. 绑定到一个IP地址和端口号
  3. 监听客户端请求
  4. 接受客户端连接
  5. 发送和接收数据

下面是详细的介绍:

  1. 创建socket

在C中使用socket函数来创建socket,语法如下:

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

其中,domain参数指定了协议域,常用的有AF_INET(IPv4)和AF_INET6(IPv6)。type参数指定了数据传输方式,常用的有SOCK_STREAM(面向连接的 TCP socket)和SOCK_DGRAM(无连接的 UDP socket)。protocol参数通常设为0,表示由系统自动选择合适的协议。

例如,创建一个TCP socket:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  1. 绑定到一个IP地址和端口号

在C中使用bind函数来将socket绑定到一个IP地址和端口号上,语法如下:

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

其中,sockfd为要绑定的socket的文件描述符,addr为一个指向sockaddr结构体的指针,用来指定IP地址和端口号,addrlen为存储地址长度的变量。

例如,将socket绑定到本地IP地址的8080端口上:

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080); // 将主机字节序转换为网络字节序
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 使用INADDR_ANY绑定到所有可用的地址

bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
  1. 监听客户端请求

在C中使用listen函数来监听socket,语法如下:

int listen(int sockfd, int backlog);

其中,sockfd为要监听的socket的文件描述符,backlog为等待连接队列的最大长度。

例如,监听socket:

listen(sockfd, 10); // backlog设为10,表示等待连接队列的最大长度为10
  1. 接受客户端连接

在C中使用accept函数来接受客户端连接,语法如下:

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

其中,sockfd为要接受连接的socket的文件描述符,addr为一个指向sockaddr结构体的指针,用来存储客户端的IP地址和端口号,addrlen为存储地址长度的变量。

例如,接受客户端连接:

struct sockaddr_in client_addr;
socklen_t client_addrlen = sizeof(client_addr);

int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addrlen);

printf("got connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

其中,inet_ntoa函数将IP地址的网络字节序整数转换为字符串形式。

  1. 发送和接收数据

在C中使用send和recv函数来发送和接收数据,语法如下:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

其中,sockfd为要发送/接收数据的socket的文件描述符,buf为数据缓冲区的地址,len为数据长度,flags为选项,通常设为0。

例如,向客户端发送数据:

send(connfd, "welcome to my server", strlen("welcome to my server"), 0);

接收客户端发送的数据:

char buffer[1024];
recv(connfd, buffer, sizeof(buffer), 0);
printf("received: %s\n", buffer);

下面是两个示例:

示例1:简单的TCP服务器和客户端

// server.c

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

int main() {
    // 创建socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 绑定到本地IP地址的8080端口上
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));

    // 监听socket
    listen(sockfd, 10);

    // 接受客户端连接,并发送欢迎消息
    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_addrlen = sizeof(client_addr);
        int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addrlen);
        printf("got connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        send(connfd, "welcome to my server\n", strlen("welcome to my server\n"), 0);

        // 接收客户端消息,并输出
        char buffer[1024];
        while (1) {
            int ret = recv(connfd, buffer, sizeof(buffer), 0);
            if (ret <= 0) {
                break;
            }
            buffer[ret] = '\0';
            printf("received: %s\n", buffer);
        }

        // 关闭连接
        close(connfd);
    }

    // 关闭socket
    close(sockfd);
    return 0;
}

// client.c

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

int main() {
    // 创建socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 连接到本地IP地址的8080端口上
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));

    // 接收服务器消息,并输出
    char buffer[1024];
    ssize_t ret = recv(sockfd, buffer, sizeof(buffer), 0);
    if (ret > 0) {
        buffer[ret] = '\0';
        printf("received: %s", buffer);
    }

    // 向服务器发送消息
    send(sockfd, "hello\n", strlen("hello\n"), 0);

    // 关闭socket
    close(sockfd);
    return 0;
}

示例2:简单的UDP服务器和客户端

// server.c

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

int main() {
    // 创建socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 绑定到本地IP地址的8080端口上
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));

    // 接收客户端消息,并回复
    struct sockaddr_in client_addr;
    socklen_t client_addrlen = sizeof(client_addr);
    char buffer[1024];
    while (1) {
        int ret = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addrlen);
        if (ret == -1) {
            perror("recvfrom");
            break;
        }
        buffer[ret] = '\0';
        printf("received: %s\n", buffer);

        sendto(sockfd, "got it\n", strlen("got it\n"), 0, (struct sockaddr *)&client_addr, client_addrlen);
    }

    // 关闭socket
    close(sockfd);
    return 0;
}

// client.c

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

int main() {
    // 创建socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 向服务器发送消息
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sendto(sockfd, "hello\n", strlen("hello\n"), 0, (struct sockaddr *)&addr, sizeof(addr));

    // 接收服务器回复,并输出
    char buffer[1024];
    struct sockaddr_in recv_addr;
    socklen_t recv_addrlen = sizeof(recv_addr);
    int ret = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&recv_addr, &recv_addrlen);
    if (ret > 0) {
        buffer[ret] = '\0';
        printf("received: %s", buffer);
    }

    // 关闭socket
    close(sockfd);
    return 0;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言中如何进行网络编程? - Python技术站

(0)
上一篇 2023年4月27日
下一篇 2023年4月27日

相关文章

  • #FREERTOS的和heap_4内存分配算法

    FreeRTOS的heap_4内存管理算法具有内存碎片合并的功能,可以有效防止内存碎片产生,使用First fit算法,在实现上与C标准库的malloc类似,但是效率更高且能进行碎片合并回收。以下是个人对源码的解析,有空再补充详细。 一、初始化 static void prvHeapInit( void ) { BlockLink_t *pxFirstFre…

    C语言 2023年4月17日
    00
  • C++实现字符格式相互转换的示例代码

    实现字符格式相互转换是C++的基础知识之一。下面,我将详细介绍如何编写C++实现字符格式相互转换的示例代码。 1. 什么是字符格式转换 字符格式转换是指将一个字符从一种格式转换到另一种格式的过程。常见的字符格式包括ASCII码、Unicode、UTF-8等。C++中提供了丰富的函数和类库来方便我们进行字符格式转换操作。 2. 示例代码 下面我们将展示如何编写…

    C 2023年5月24日
    00
  • 战地4出现0xc000007b错误怎么办 具体解决方法分享

    战地4出现0xc000007b错误怎么办?——具体解决方法分享 问题描述 在运行战地4时,可能会遇到“0xc000007b”错误,导致游戏无法启动或崩溃。这种错误通常是由多个因素引起的,包括操作系统、软件与驱动程序的错误等。 解决方法 以下提供几种解决“0xc000007b”错误的方法。 方法一:安装最新的操作系统更新 在Windows 10上,您可以打开“…

    C 2023年5月23日
    00
  • awk命令、awk编程语言详细介绍和实例

    AWK命令、AWK编程语言详细介绍和实例 什么是AWK? AWK 是一种处理文本文件的工具,它的名字是由其创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的首字母组成的。 AWK 可以将数据分成记录和字段,是一种灵活、功能强大的文本分析工具。它最初是为 LINUX 操作系统设计的,现在已经移植到许多其他操作…

    C 2023年5月22日
    00
  • C++11中的变长模板的示例详解

    让我来详细讲解“C++11中的变长模板的示例详解”的完整攻略: 什么是变长模板 在C++标准库中,存在一个叫做std::tuple的工具类,可以用于表示可以持有任意个元素的集合。其中元素的类型可以不相同。这里的“任意个元素”就是指可以持有任意个类型参数。这种由C++模板机制提供的自由组合类型的能力,就是变长模板。 变长模板的语法 变长模板的语法非常简单,就是…

    C 2023年5月23日
    00
  • C语言实现动态顺序表的实现代码

    让我来为大家详细讲解一下如何使用C语言实现动态顺序表的实现代码。 1. 动态顺序表的概述 动态顺序表是一种线性表,它基于数组实现。动态顺序表可以自动扩充或缩小其容量以存储数据。动态顺序表中元素的位置是按照它们在数组中的位置来确定的。它们在内存中是连续存储的,因此它们可以通过下标快速访问。 2. 动态顺序表的实现 我们使用C语言的方法来实现动态顺序表。首先,我…

    C 2023年5月23日
    00
  • 全排列算法的原理和实现代码

    全排列算法是指对于给定的一组数(假设有n个数),求出其所有排列方式的算法。具体来说,假设有{1,2,3}这3个数字,那么它们的全排列就有6种,分别为: {1,2,3}, {1,3,2}, {2,1,3}, {2,3,1}, {3,1,2}, {3,2,1} 下面我们分别介绍一下全排列算法的原理以及具体实现代码。 全排列算法的原理 全排列算法的核心思路是回溯法…

    C 2023年5月22日
    00
  • C语言中实现KMP算法的实例讲解

    C语言中实现KMP算法的实例讲解 什么是KMP算法 KMP算法(Knuth-Morris-Pratt algorithm)是一种字符串匹配算法,可以在$O(n)$的时间复杂度内实现字符串的查找。KMP算法主要解决的问题是在主串S中查找模式串T的位置,KMP算法的核心思想是通过预处理模式串,构造一个跳转表格,从而在匹配的过程中能够避免主串S的回溯,从而提高算法…

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