当前位置: 首页 > news >正文

Linux网络编程-极简HTTPUDP服务器

HTTP服务器

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 2048void handle_client(int client_socket) {char buffer[BUFFER_SIZE];recv(client_socket, buffer, sizeof(buffer) - 1, 0);  printf("Received request:\n%s\n", buffer);char response[] = "HTTP/1.1 200 OK\r\n""Content-Type: text/plain\r\n""Content-Length: 15\r\n""Connection: close\r\n\r\n""Hello, World!\r\n";send(client_socket, response, sizeof(response) - 1, 0);  close(client_socket);
}int main() {int server_socket, client_socket;struct sockaddr_in server_address, client_address;socklen_t client_len;server_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket == -1) {perror("Could not create socket");exit(1);}server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = INADDR_ANY;server_address.sin_port = htons(PORT);if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {perror("Bind failed");exit(1);}if (listen(server_socket, 10) == -1) {perror("Listen failed");exit(1);}printf("HTTP server is running on port %d ...\n", PORT);while (1) {client_len = sizeof(client_address);client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_len);if (client_socket == -1) {perror("Accept failed");continue;}handle_client(client_socket);}close(server_socket);return 0;
}

HTTP客户端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>#define SERVER_PORT 8080
#define BUFFER_SIZE 2048int main(int argc, char *argv[]) {int client_socket;struct sockaddr_in server_address;char buffer[BUFFER_SIZE];// 检查命令行参数if (argc != 2) {printf("Usage: %s <Server IP>\n", argv[0]);exit(1);}client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {perror("Could not create socket");exit(1);}server_address.sin_family = AF_INET;server_address.sin_port = htons(SERVER_PORT);if (inet_pton(AF_INET, argv[1], &server_address.sin_addr) <= 0) {perror("inet_pton() failed");exit(1);}// 连接到服务器if (connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {perror("Connect failed");close(client_socket);exit(1);}// 向服务器发送HTTP请求char request[] = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";send(client_socket, request, strlen(request), 0);// 接收服务器响应int bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);if (bytes_received == -1) {perror("Error receiving data");close(client_socket);exit(1);}buffer[bytes_received] = '\0';printf("Received from server:\n%s\n", buffer);close(client_socket);return 0;
}

或者在浏览器或者使用curl工具访问http://localhost:8080,也能够看到来自服务器的“Hello, World!”响应。

curl http://localhost:8080
curl -X POST -d "param1=value1&param2=value2" http://localhost:8080

UDP服务器

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 2048void handle_client(int server_socket, struct sockaddr_in *client_address, socklen_t client_len) {char buffer[BUFFER_SIZE];int bytes_received = recvfrom(server_socket, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)client_address, &client_len);if (bytes_received == -1) {perror("Error receiving data");return;}buffer[bytes_received] = '\0';printf("Received request from %s:%d\n%s\n", inet_ntoa(client_address->sin_addr), ntohs(client_address->sin_port), buffer);char response[] = "Hello, World from UDP!";sendto(server_socket, response, sizeof(response) - 1, 0, (struct sockaddr *)client_address, client_len);
}int main() {int server_socket;struct sockaddr_in server_address, client_address;socklen_t client_len;server_socket = socket(AF_INET, SOCK_DGRAM, 0);if (server_socket == -1) {perror("Could not create socket");exit(1);}server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = INADDR_ANY;server_address.sin_port = htons(PORT);if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {perror("Bind failed");exit(1);}printf("UDP server is running on port %d...\n", PORT);while (1) {client_len = sizeof(client_address);handle_client(server_socket, &client_address, client_len);}close(server_socket);return 0;
}

UDP客户端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>#define SERVER_PORT 8080
#define BUFFER_SIZE 2048int main(int argc, char *argv[]) {int client_socket;struct sockaddr_in server_address;char buffer[BUFFER_SIZE];// 检查命令行参数if (argc != 2) {printf("Usage: %s <Server IP>\n", argv[0]);exit(1);}client_socket = socket(AF_INET, SOCK_DGRAM, 0);if (client_socket == -1) {perror("Could not create socket");exit(1);}memset(&server_address, 0, sizeof(server_address));server_address.sin_family = AF_INET;server_address.sin_port = htons(SERVER_PORT);if (inet_pton(AF_INET, argv[1], &server_address.sin_addr) <= 0) {perror("inet_pton() failed");exit(1);}// 向服务器发送消息char message[] = "Hello, UDP Server!";sendto(client_socket, message, strlen(message), 0, (struct sockaddr *)&server_address, sizeof(server_address));// 接收来自服务器的响应int bytes_received = recvfrom(client_socket, buffer, BUFFER_SIZE - 1, 0, NULL, NULL);if (bytes_received == -1) {perror("Error receiving data");exit(1);}buffer[bytes_received] = '\0';printf("Received from server: %s\n", buffer);close(client_socket);return 0;
}

或者使用以下命令向UDP服务器发送数据:

echo "Your message here" | nc -u -w1 localhost 8080

为什么 send()recv() 适用于TCP而不是UDP

TCP (Transmission Control Protocol) 是一个面向连接的协议。当我们谈论TCP连接时,我们指的是一个由客户端套接字和服务器套接字组成的持久的网络连接。这意味着,一旦建立了TCP连接,双方都知道对方的IP地址和端口号,因此不需要在每次数据交换时重新指定。

由于这种固定的连接特性,当我们想要通过已经建立的TCP连接发送或接收数据时,不需要再次指定远程的地址和端口。这就是为什么 send()recv() 适用于TCP:它们只发送和接收数据,不涉及地址信息。

另一方面,UDP (User Datagram Protocol) 是一个无连接的协议。这意味着每次数据包的发送都是独立的,没有固定的连接或对端信息与其相关联。因此,当我们使用UDP发送数据时,需要指定要将数据发送到的地址和端口。这就是 sendto()recvfrom() 的用途。

总结:

  • TCP是面向连接的,一旦连接建立,系统就知道数据将被发送到哪里,因此只需要 send()recv()
  • UDP是无连接的,所以每次发送数据都需要指定目的地,这就是为什么需要 sendto()recvfrom()

当然,技术上可以为UDP使用 connect() 来设置默认的远程地址和端口,然后使用 send()recv(),但这样做是非典型的,并可能导致与UDP的无连接特性不一致的行为。


当我们说SOCK_STREAM(如TCP)为我们提供了一个连续的字节流,并且没有内在的消息边界,这是什么意思呢?

  1. 连续的字节流

    • 当我们使用TCP发送数据,是在向一个开放的连接发送一个连续的字节流。例如,如果连续调用三次send()函数,发送三个字符串,它们可能会被接收端作为一个连续的字节流接收。
    • 不存在固定的消息大小或结构,我们可以任意发送任何大小的数据。
  2. 没有内在的消息边界

    • 在TCP中,数据的发送和接收是流式的,没有固定的消息边界。这意味着,如果发送方连续发送了两个数据块,接收方没有办法仅通过TCP来知道这两个数据块是如何分隔的。接收方可能在一个recv()调用中接收到两个数据块的部分或全部。
    • 例如,如果发送方连续执行两次send(),分别发送字符串"HELLO"和"WORLD",接收方可能需要多次recv()调用来接收这些数据,或者可能在一个recv()调用中接收到字符串"HELLOWORLD"。

这种没有消息边界的特性与SOCK_DGRAM(如UDP)形成了对比,在UDP中,每个sendto()调用发送的数据都被视为一个独立的消息,且在接收端通过一个recvfrom()调用完整地接收。

这就是为什么在使用TCP时,应用程序往往需要自己实现某种消息边界的机制,例如通过使用特定的分隔符、固定长度的头部或其他协议来定义消息的开始和结束。


SOCK_DGRAM 提供了一个有边界的服务。这意味着,当我们使用 SOCK_DGRAM(如UDP)发送一个数据报,接收端会将这个数据报作为一个整体进行处理,不会将它与其他数据报合并或分割。每个 sendto() 调用对应一个完整且单独的消息,该消息在接收端使用一个 recvfrom() 调用完整接收。

换句话说,数据报协议保留了消息边界。例如,如果发送方调用了两次 sendto(),接收方也必须调用两次 recvfrom() 来接收这两条消息。这与 SOCK_STREAM(如TCP)不同,在流式协议中,数据是一个连续的字节流,没有内在的消息边界。


关于curl命令和nc命令的详细介绍以及网络编程中常用的函数说明,读者可移步至以下博客:

Linux- curl命令

Linux中的nc命令

Linux网络编程- recvfrom() & sendto()

Linux- 网络编程初探

相关文章:

Linux网络编程-极简HTTPUDP服务器

HTTP服务器 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h>#define PORT 8080 #define BUFFER_SIZE 2048void handle_client(int client_socket) {char buffer[BUFFER_SIZE];recv(cl…...

虚拟化、容器与Docker基本介绍以及安装部署(Docker 基本管理)

目录 1 Docker 概述 1.1 Docker与虚拟机的区别 1.2 容器在内核中支持2种重要技术 1.3 Docker核心概念 2 安装 Docker 2 Docker 镜像操作 2.1 搜索镜像 2.2 获取镜像 2.3 镜像加速下载 2.4 查看镜像信息 2.4.1 查看下载的镜像文件信息 2.4.2 查看下载到本地的所有镜像…...

Spring Boot中捕获异常错误信息并将其保存到数据库中

Spring Boot中捕获异常错误信息并将其保存到数据库中: 1.创建数据库表&#xff1a; 首先&#xff0c;您需要创建一个用于存储异常信息的数据库表。可以使用SQL脚本或者使用Hibernate实体类来创建表。以下是一个用于存储异常信息的表的示例SQL&#xff1a; CREATE TABLE erro…...

CNN记录】pytorch中flatten函数

pytorch原型 torch.flatten(input, start_dim0, end_dim- 1) 作用&#xff1a;将连续的维度范围展平维张量&#xff0c;一般写再某个nn后用于对输出处理&#xff0c; 参数&#xff1a; start_dim&#xff1a;开始的维度 end_dim&#xff1a;终止的维度&#xff0c;-1为最后…...

科普长文--网络安全拟态防御技术概念及应用

网络安全拟态防御技术概念 什么是网络安全拟态防御? 网络安全拟态防御技术是一种基于生物拟态原理,利用动态异构冗余构造、拟态伪装机制、测不准效应等手段,实现网络空间的主动防御和内生安全的技术。它是由中国工程院院士邬江兴首创的,旨在应对网络空间中的各种未知威胁…...

框架篇

一、Spring中的单例Bean是线程安全的吗 二、AOP相关面试题 三、Spring中的事务 四、Spring中事务失效的场景有 五、Spring bean的生命周期 六、Spring的循环依赖 七、SpringMVC的执行流程 八、自动配置原理 九、Spring框架常见的注解 十、Mybatis的执行流程 十一、MyBatis延迟加…...

Spring MVC(中)

1、Spring MVC视图&#xff1a; SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户 SpringMVC视图的种类很多&#xff0c;默认有转发视图和重定向视图 当工程引入jstl的依赖&#xff0c;转发视图会自动转换为JstlView …...

10月19日,每日信息差

今天是2023年10月19日&#xff0c;以下是为您准备的17条信息差 第一、中国海洋石油遭南向资金净卖出2.38亿港元 第二、阅文集团侯晓楠&#xff1a;网文已经成为中国文化的一张全球名片。据了解&#xff0c;2022年以来&#xff0c;阅文已经在海外上线了自制的300多部动漫影视作…...

【VSCode】解决Open in browser无效

问题描述&#xff1a; 在VSCode中无论是点击右键&#xff0c;选择在默认浏览器中打开&#xff0c;还是按快捷键alt b都没有反应。 解决办法&#xff1a; 右击文件 --> 在文件资源管理器中显示 右击文件&#xff0c;选择属性 点击更改 选择用默认浏览器打开 最后 此时…...

测试饱和了? 大数据测试就业薪资和前景究竟怎么样?

随着不断有转行人员及毕业的大学生进入IT行业&#xff0c;在很多外界人眼里&#xff0c;这个行业的“缺口”已满&#xff0c;人员趋于饱和&#xff0c;但事实真的这样吗&#xff1f;还真没有。只是最基础的岗位需求在慢慢变少了&#xff0c;但行业中比较深的细分岗位&#xff0…...

DDR3笔记 频率配置

可参考 基于FPGA的DDR3设计&#xff08;2&#xff09;DDR3各时钟频率及带宽分析 - 知乎 (zhihu.com) DDR3的时钟频率配置要看两个手册&#xff1a; 1.DDR3器件的手册。 2.开发板芯片的手册 器件 器件名称&#xff1a;MT41J128M16JT-125:K tCK 1.25ns&#xff0c;就可以算出…...

数据结构与算法-(10)---列表(List)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…...

Node-Web模块的用法

题记 node.js中web模块的用法&#xff0c;以下是具体操作过程和代码。 Web服务器一般指网站服务器&#xff0c;是指驻留于因特网上某种类型计算机的程序&#xff0c;Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL&#xff0c;与客户端的…...

基于TCP的RPC服务

TCP服务器上的RPC&#xff0c;通过创建一个服务器进程监听传入的tcp连接&#xff0c;并允许用户 通过此TCP流执行RPC命令 -module(tr_server). -author("chen"). -behaviour(gen_server).%% API -export([start_link/1,start_link/0,get_count/0,stop/0 ]).-export(…...

docker报错问题解决:Error Invalid or corrupt jarfile app.jar

文章目录 1.问题描述2.问题分析3.问题解决 1.问题描述 此时处在 /home/ubuntu/app 目录下&#xff0c;并且在该目录下有一个 jenkins-0.0.1-SNAPSHOT.jar。 我在 /home/ubuntu/app 目录下执行了 docker 容器运行命令&#xff1a; # 映射 8859 端口 # 容器名为 jenkins-demo #…...

Day 09 python学习笔记

函数 装饰器 回顾内容&#xff1a; 函数可以作为参数进行传递函数可以作为返回值函数名称可以像变量一样进行赋值操作 装饰器&#xff1a;要求记住结论 引入&#xff1a; def play_dnf():print("你好啊&#xff0c;我是赛利亚&#xff0c;今天又是美好的一天")def p…...

力扣labuladong——一刷day02

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣876. 链表的中间结点二、力扣142. 环形链表 II三、力扣160. 相交链表四、力扣141. 环形链表 前言 一、力扣876. 链表的中间结点 /*** Definition for …...

【小白专用23.10.22 已验证】windows 11 安装PHP8.2 +Apache2.4

环境说明 windows:windows 11 x64apache: Apache/2.4.43php :php-8.2.11 一.php 1、PHP下载 PHP For Windows: Binaries and sources Releases 注意&#xff1a; 1.要下载Thread Safe&#xff0c;否则没有php8apache2_4.dll这个文件&#xff1b;如果使用Apache作为服务器…...

Nmap端口服务 之 CentOS7 关于启动Apache(httpd)服务、telnet服务、smtp服务、ftp服务、sftp服务

Nmap端口服务 之 CentOS7 关于启动Apache(httpd)服务、telnet服务、smtp服务、ftp服务、sftp服务 一. CentOS7 安装配置SFTP服务器详解一、SFTP简介二、关闭防火墙三、安装SSH服务在CentOS7中,sftp只是ssh的一部分,所以采用yum来安装ssh服务即可1. 查看是否已经安装了ssh2.…...

为什么 glBegin 未被定义 未定义的标识符,使用新的 API(LearnOpenGL P2)

文章目录 弃用的 glBegin & glEnd使用新 API 的示例 弃用的 glBegin & glEnd 环境&#xff1a;glfw 3.3.8 glad core OpenGL 初学者在尝试使用 glBegin 和 glEnd 函数来绘制三角形时&#xff0c;有可能找到使用这些函数的文章、代码文献 但许多这些函数已经在OpenG…...

设计模式——抽象工厂设计模式(创建型)

摘要 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在提供一个接口&#xff0c;用于创建一系列相关或依赖的对象&#xff0c;无需指定具体类。它通过抽象工厂、具体工厂、抽象产品和具体产品等组件构建&#xff0c;相比工厂方法模式&#xff0c;能创建一个产品族。该模…...

人工智能在智能教育中的创新应用与未来趋势

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;教育领域正经历着一场深刻的变革。智能教育通过引入AI、物联网&#xff08;IoT&#xff09;、大数据和云计算等前沿技术&#xff0c;正在实现教育的个性化、智能化和高效化。本文将探讨人工智能在智能教育中的…...

【设计模式-3.7】结构型——组合模式

说明&#xff1a;本文介绍结构型设计模式之一的组合模式 定义 组合模式&#xff08;Composite Pattern&#xff09;又叫作整体-部分&#xff08;Part-Whole&#xff09;模式&#xff0c;它的宗旨是通过将单个对象&#xff08;叶子节点&#xff09;和组合对象&#xff08;树枝…...

.NET 8集成阿里云短信服务完全指南【短信接口】

文章目录 前言一、准备工作1.1 阿里云账号准备1.2 .NET 8项目创建 二、集成阿里云短信SDK2.1 安装NuGet包2.2 配置阿里云短信参数2.3 创建配置类 三、实现短信发送服务3.1 创建短信服务接口3.2 实现短信服务3.3 注册服务 四、创建控制器五、测试与优化5.1 单元测试5.2 性能优化…...

【设计模式】门面/外观模式

MySQL &#xff0c;MyTomcat 的启动 现在有 MySQL &#xff0c;MyTomcat 类&#xff0c;需要依次启动。 public class Application {public static void main(String[] args) {MySQL mySQL new MySQL();mySQL.initDate();mySQL.checkLog();mySQL.unlock();mySQL.listenPort(…...

【Redis】zset 类型

zset 一. zset 类型介绍二. zset 命令zaddzcard、zcountzrange、zrevrange、zrangebyscorezpopmax、zpopminzrank、zrevrank、zscorezrem、zremrangebyrank、zremrangebyscorezincrby阻塞版本命令&#xff1a;bzpopmax、bzpopmin集合间操作&#xff1a;zinterstore、zunionstor…...

【含文档+PPT+源码】基于微信小程序的旅游论坛系统的设计与实现

项目介绍 本课程演示的是一款基于微信小程序的旅游论坛系统的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 …...

202403-02-相似度计算 csp认证

其实这个问题就是求两篇文章的词汇的交集和并集&#xff0c;首先一说到并集&#xff0c;我就想到了set集合数据结构&#xff0c;set中的元素必须唯一。 STL之set的基本使用–博客参考 所以将两个文章的词汇全部加入set中&#xff0c;并求出set的大小&#xff0c;即为并集的大小…...

echarts显示/隐藏标签的同时,始终显示饼图中间文字

显示标签的同时&#xff0c;始终显示饼图中间文字 let _data this.chartData.slice(1).map((item) > ({name: item.productName,value: Number(item.stock), })); this.chart.setOption({tooltip: {trigger: item,},graphic: { // 重点在这里&#xff08;显示饼图中间文字&…...

Fullstack 面试复习笔记:项目梳理总结

Fullstack 面试复习笔记&#xff1a;项目梳理总结 之前的笔记&#xff1a; Fullstack 面试复习笔记&#xff1a;操作系统 / 网络 / HTTP / 设计模式梳理Fullstack 面试复习笔记&#xff1a;Java 基础语法 / 核心特性体系化总结 这篇笔记主自用&#xff0c;系统地梳理一下最近…...