C语言的网络编程

目录

引言

一、TCP/IP概述

1. TCP(Transmission Control Protocol)

2. UDP(User Datagram Protocol)

二、Socket编程基础

1. 服务器端

2. 客户端

三、URL与HTTP编程

1. 使用libcurl进行HTTP请求

表格总结

TCP/IP与Socket编程

网络编程库

四、网络通信应用

1. 简单聊天程序

五、文件传输应用

表格总结

网络编程常用函数

项目应用举例

总结


引言

网络编程是C语言中一个重要的应用领域,特别在开发基于TCP/IP的网络应用时,网络编程起着至关重要的作用。通过网络编程,程序可以与其他计算机进行数据交换,实现分布式计算和网络服务。本篇文章将详细介绍C语言中的网络编程,包括TCP/IP概述、Socket编程基础、URL与HTTP编程,以及网络通信应用,帮助读者全面理解和掌握C语言中的网络编程技术。

一、TCP/IP概述

TCP/IP是因特网的基础协议,它定义了一组协议来实现网络数据通信。TCP/IP协议分为多个层次,最常用的协议包括TCP和UDP,这些协议在网络编程中至关重要。

1. TCP(Transmission Control Protocol)

TCP是面向连接的协议,提供可靠的数据传输服务。TCP在传输数据之前需要建立连接,并保证数据按顺序到达。

2. UDP(User Datagram Protocol)

UDP是面向无连接的协议,提供不可靠的数据传输服务。UDP不需要建立连接,并不保证数据到达的顺序。

二、Socket编程基础

Socket是网络编程的基础设施,通过它可以实现通信双方的数据交换。Socket编程分为服务器端和客户端。

1. 服务器端

服务器端需要创建Socket、绑定地址和端口、监听连接并接受客户端连接。

示例代码:

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

#define PORT 8080

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    const char *message = "Hello from server";

    // 创建socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 绑定socket到地址和端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    // 接受客户端连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    read(new_socket, buffer, 1024);
    printf("Message from client: %s\n", buffer);
    send(new_socket, message, strlen(message), 0);
    printf("Hello message sent\n");

    close(new_socket);
    close(server_fd);

    return 0;
}

2. 客户端

客户端需要创建Socket、连接服务器,并发送和接收数据。

示例代码:

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

#define PORT 8080

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char *message = "Hello from client";
    char buffer[1024] = {0};

    // 创建socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("\nSocket creation error\n");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 转换地址
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        printf("\nInvalid address\n");
        return -1;
    }

    // 连接服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("\nConnection failed\n");
        return -1;
    }

    send(sock, message, strlen(message), 0);
    printf("Hello message sent\n");
    read(sock, buffer, 1024);
    printf("Message from server: %s\n", buffer);

    close(sock);
    return 0;
}

三、URL与HTTP编程

在网络应用中,URL和HTTP协议是常用的技术。C语言通过libcurl等库实现HTTP编程。

1. 使用libcurl进行HTTP请求

libcurl是一个功能强大的库,支持多种协议,包括HTTP、FTP等。

示例代码:

#include <stdio.h>
#include <curl/curl.h>

int main() {
    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/");

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);

        /* Check for errors */
        if (res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));

        /* Always cleanup */
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return 0;
}

在上面的示例中,通过libcurl进行HTTP GET请求并获取网页内容。

表格总结

TCP/IP与Socket编程

操作服务器端函数客户端函数
创建Socketsocket(AF_INET, SOCK_STREAM, 0)socket(AF_INET, SOCK_STREAM, 0)
绑定地址和端口bind(server_fd, (struct sockaddr *)&address, sizeof(address))
监听连接listen(server_fd, 3)
接受连接accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))
读取数据read(new_socket, buffer, 1024)read(sock, buffer, 1024)
发送数据send(new_socket, message, strlen(message), 0)send(sock, message, strlen(message), 0)

网络编程库

操作示例
libcurlHTTP GET请求curl_easy_perform(curl)
POSIX sockets创建Socket,连接与传输数据socketconnectsendread

四、网络通信应用

通过网络编程,可以实现各种网络通信应用,如聊天程序、文件传输、网络监控等。

1. 简单聊天程序

下面是一个简单的聊天程序示例,使用TCP进行网络通信。这是一个简化版的聊天系统,由一个服务器端和多个客户端组成。服务器端负责处理多个客户端的连接和消息转发,而客户端负责与服务器进行消息交换。

服务器端:

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

#define PORT 9090
#define MAX_CLIENTS 100

int clients[MAX_CLIENTS];
int client_count = 0;
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;

void *handle_client(void *client_socket) {
    int new_socket = *(int *)client_socket;
    char buffer[1024];
    int bytes_read;

    while ((bytes_read = read(new_socket, buffer, sizeof(buffer))) > 0) {
        buffer[bytes_read] = '\0';
        printf("Message from client: %s", buffer);

        // Send message to all clients
        pthread_mutex_lock(&clients_mutex);
        for (int i = 0; i < client_count; i++) {
            if (clients[i] != new_socket) {
                send(clients[i], buffer, strlen(buffer), 0);
            }
        }
        pthread_mutex_unlock(&clients_mutex);
    }

    close(new_socket);
    return NULL;
}

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    pthread_t tid;

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 3);

    printf("Server is listening on port %d\n", PORT);

    while ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) >= 0) {
        pthread_mutex_lock(&clients_mutex);
        clients[client_count++] = new_socket;
        pthread_mutex_unlock(&clients_mutex);
        pthread_create(&tid, NULL, handle_client, (void *)&new_socket);
    }

    close(server_fd);
    return 0;
}

客户端:

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

#define PORT 9090

void *receive_messages(void *sock) {
    int sockfd = *(int *)sock;
    char buffer[1024];
    int bytes_read;

    while ((bytes_read = read(sockfd, buffer, sizeof(buffer))) > 0) {
        buffer[bytes_read] = '\0';
        printf("%s", buffer);
    }

    return NULL;
}

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[1024];
    pthread_t tid;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    pthread_create(&tid, NULL, receive_messages, (void *)&sock);

    while (1) {
        fgets(buffer, sizeof(buffer), stdin);
        send(sock, buffer, strlen(buffer), 0);
    }

    close(sock);
    return 0;
}

五、文件传输应用

文件传输是网络编程中的常见任务,下面是一个简单的文件传输示例,展示如何通过网络传输文件。

服务器端:

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

#define PORT 9090
#define CHUNK_SIZE 1024

void send_file(int socket, const char *filename) {
    FILE *file = fopen(filename, "rb");
    char buffer[CHUNK_SIZE];
    int bytes_read;

    if (file == NULL) {
        perror("File open error");
        return;
    }

    while ((bytes_read = fread(buffer, 1, CHUNK_SIZE, file)) > 0) {
        send(socket, buffer, bytes_read, 0);
    }

    fclose(file);
}

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    const char *filename = "server_file.txt";

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 3);

    new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen);

    send_file(new_socket, filename);

    close(new_socket);
    close(server_fd);

    return 0;
}

客户端:

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

#define PORT 9090
#define CHUNK_SIZE 1024

void receive_file(int socket, const char *filename) {
    FILE *file = fopen(filename, "wb");
    char buffer[CHUNK_SIZE];
    int bytes_read;

    if (file == NULL) {
        perror("File open error");
        return;
    }

    while ((bytes_read = read(socket, buffer, CHUNK_SIZE)) > 0) {
        fwrite(buffer, 1, bytes_read, file);
    }

    fclose(file);
}

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    const char *filename = "client_file.txt";

    sock = socket(AF_INET, SOCK_STREAM, 0);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    receive_file(sock, filename);

    close(sock);
    return 0;
}

在上面的示例中,服务器端负责读取文件并通过网络发送给客户端,而客户端负责接收文件并保存到本地。这简单实现了文件传输的基本功能。

表格总结

网络编程常用函数

操作函数示例
创建Socketsocket(AF_INET, SOCK_STREAM, 0)sock = socket(AF_INET, SOCK_STREAM, 0);
绑定地址和端口bind(server_fd, (struct sockaddr *)&address, sizeof(address))bind(server_fd, (struct sockaddr *)&address, sizeof(address));
监听连接listen(server_fd, 3)listen(server_fd, 3);
接受连接accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
连接服务器connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
读取数据read(socket, buffer, sizeof(buffer))read(new_socket, buffer, sizeof(buffer));
发送数据send(socket, buffer, strlen(buffer), 0)send(sock, buffer, strlen(buffer), 0);

项目应用举例

功能服务器端文件处理客户端文件处理说明
简单聊天程序read, sendfgets, read, send双方向消息交流
文件传输程序fopen, fread, sendfopen, fwrite, read服务器发送文件,客户端接收

总结

网络编程在C语言中是一个非常重要的主题,通过Socket编程,程序能够进行网络通信,构建分布式系统和网络应用程序。本文详细介绍了TCP/IP协议、Socket编程基础、URL与HTTP编程,并通过实际示例展示了如何实现网络聊天和文件传输。通过掌握这些知识,编程者可以设计和实现高效、可靠的网络应用,为构建复杂的分布式系统打下坚实基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/727801.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity | Editor强化工具】项目备忘录工具

经常会被美术和策划同事反复询问某几个问题&#xff0c;每次都要翻Wiki链接给他们&#xff0c;非常折磨人&#xff0c;所以做了个可以在Unity内部显示备忘录的小工具&#xff0c;能够减少一些查找成本&#xff08;另外我觉得&#xff0c;让他们养成查看Unity内触手可及的信息的…

报错:ZeroDivisionError_ division by zero

问题&#xff1a;除数为0 原代码错误来源 # 归一化 , 保留6位小数 w round(w / img_w, 6) h round(h / img_h, 6) cx round(cx / img_w, 6) cy round(cy / img_h, 6) # print(cls_id, cx, cy, w, h) # 结果保存到数据labels文件夹中的txt文件 out_file.write(str(cls_id) …

Redis 主从复制+哨兵+集群

1、总结写在前面 Redis 集群 数据分片 高可用性 Redis 哨兵 主从复制 故障转移 2、主从复制 2.1、准备配置 查看docker 容器 ip docker inspect 容器id | grep IPAddressdocker inspect -f{{.Name}} {{.NetworkSettings.IPAddress}} $(docker ps -aq)修改配置文件 初始…

从零开始搭建创业公司全新技术栈解决方案

从零开始搭建创业公司全新技术栈解决方案 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程、bug解决思路、开发工具教程、前沿科技资讯、产品评测图文、产品使用体…

Zookeeper 一、Zookeeper简介

1.分布式系统定义及面临的问题 分布式系统是同时跨越多给物理主机&#xff0c;独立运行的多个软件所组成的系统。类比一下&#xff0c;分布式系统就是一群人一起干活。人多力量大&#xff0c;每个服务器的算力是有限的&#xff0c;但是通过分布式系统&#xff0c;由n个服务器组…

Flink 流批一体场景应用及落地情况

摘要&#xff1a;本文由阿里云 Flink 团队苏轩楠老师撰写&#xff0c;旨在介绍 Flink 流批一体在几个常见场景下的应用。内容主要分为以下四个部分&#xff1a; 主要场景 落地情况 未来展望 总结 上篇&#xff1a;流批一体技术简介 在上篇文章中&#xff0c;给大家整体介绍…

有关计算素数的算法

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝黑暗的笼罩更会凸显光明的可贵! 一、引言 什么是素数 素数,也被称为质数,是指在大于1的自然数中,只能被1和它本身…

【ai】tx2-nx:安装深度学习环境及4.6对应pytorch

参考:https://www.waveshare.net/wiki/Jetson_TX2_NX#AI.E5.85.A5.E9.97.A8 英伟达2021年发布的的tritionserver 2.17 版本中,backend 有tensorflow1 和 onnxruntime ,他们都是做什么用的,作为backend 对于 triton 推理server意义是什么,是否应该有pytorch? Triton Infer…

小程序中用font-spider压缩字体后,字体没效果(解决办法)

因为项目中需要引入外部字体&#xff0c;有两种方案&#xff0c; 第一是把字体下载到本地&#xff0c; 第二种是cdn请求服务器放字体的地址 但是小程序是有大小限制的&#xff0c;所以必须要压缩字体大小&#xff0c;这时候有些人就说了&#xff0c;那把字体放在服务器上&a…

从复用性角度阐述中台建设

目录 复用性中台定义深思中台建设产品线形态何时演变中台能力落地中台 业务中台架构总结 技术学习永不止步&#xff0c;最近也是看了很多关于架构设计相关的专栏&#xff0c;慢慢总结出来一部分知识&#xff0c;代入自己的思考与理解&#xff0c;以及结合并反思自己之前公司的架…

windows和linux下清空Redis

前言 在本文中&#xff0c;我们将详尽阐述在Windows与Linux操作系统中有效清除Redis缓存的实践方法&#xff0c;旨在为您提供清晰、高效的指导流程&#xff0c;确保数据管理的灵活性与效率。 windows下推荐两款可视化工具 Another Redis Desktop Manager 这是我用的最多也是最…

安卓手机删除的照片如何恢复?2个有效方法,教你找回

手机相册就像是我们的私人宝藏&#xff0c;里面装满了无数珍贵的回忆。但是&#xff0c;如果你不小心把里面的宝贝照片给删了&#xff0c;那可真是让人欲哭无泪啊&#xff01;删除的照片如何恢复&#xff1f;今天&#xff0c;我要给你介绍几个方法&#xff0c;让你轻松找回那些…

网络编程(二)TCP编程 TCP粘包问题

文章目录 一、TCP网络编程&#xff08;一&#xff09;流程&#xff08;二&#xff09;相关函数1. socket2. bind3. listen4. accept5. connect 二、收发函数&#xff08;一&#xff09;send函数&#xff08;二&#xff09;recv函数 三、TCP粘包问题&#xff08;一&#xff09;将…

linux精通 4.1

2.1.3 http服务器实现 目的 reactor应用——webserver webclient 每次上课前 看大纲down code 复习&#xff1a; 不行啊 编译给的代码报错啊 给的最新的不是0430那一版就不行啊 reactor.c:(.text0x254): relocation truncated to fit: R_X86_64_PC32 against symbol begin de…

Gobject tutorial 八

The GObject base class Object memory management Gobject的内存管理相关的API很复杂&#xff0c;但其目标是提供一个基于引用计数的灵活的内存管理模式。 下面我们来介绍一下&#xff0c;与管理引用计数相关的函数。 Reference Count 函数g_object_ref和g_object_unref的…

车载测试面试项目看这一套就够了!车载测试___自我讲解项目

面试官您好&#xff0c;我叫xx来自安微&#xff0c;今年xx岁&#xff0c;毕业于安微新华学院&#xff0c;我是从2017年开始接触软件测试行业&#xff0c;目前从事软件测试工作有5年多时间&#xff0c;第一家公司做了电商和进销存项目app和web都有做过&#xff0c;上家公司做了车…

Python使用策略模式实现绘图功能

策略模式&#xff08;Strategy Pattern&#xff09;:允许定义一系列算法&#xff0c;将它们封装起来&#xff0c;使得它们可以互换。 实现绘制不同类型的图表&#xff08;如折线图、柱状图和饼图&#xff09;功能。 下面是一个示例&#xff0c;展示如何传入横坐标和纵坐标内容…

Spring Boot集成tablesaw插件快速入门

1 什么是tablesaw&#xff1f; Tablesaw是一款Java的数据可视化库&#xff0c;主要包括两部分&#xff1a; 数据解析库&#xff0c;主要用于加载数据&#xff0c;对数据进行操作(转化&#xff0c;过滤&#xff0c;汇总等)&#xff0c;类比Python中的Pandas库&#xff1b; 数据…

JVM中的垃圾回收机制

文章目录 什么是垃圾为什么需要垃圾回收早期垃圾回收Java的垃圾回收机制垃圾回收主要关注的区域垃圾判定算法引用计数算法可达性分析算法 垃圾收集算法标记清除算法复制算法标记整理算法分代收集思想增量收集算法分区算法 什么是垃圾 垃圾回收&#xff08;Garbage Collection&…

Java面试八股之Mybatis和JPA的区别

Mybatis和JPA的区别 Mybatis 和 JPA&#xff08;Java Persistence API&#xff09;是两种在 Java 应用程序中用于数据持久化的框架&#xff0c;它们各有特点和适用场景。下面是它们之间的一些主要区别&#xff1a; 映射方式&#xff1a; Mybatis 是半自动的 ORM 框架&#xf…