【网络编程】实现服务器端和客户端的通讯的简单程序
套接字是什么?
服务端接受连接请求的套接字创建过程可分为以下4步:
1、调用socket创建套接字
2、调用bind函数分配IP地址和端口号
3、调用listen函数转换为可接受请求状态
4、调用accept函数受理连接请求
1、调用socket创建套接字
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
使用 socket() 函数创建一个新的套接字,并将其赋值给变量 serv_sock。
PF_INET:这个参数指定了套接字的地址族,即协议族。在这里,PF_INET表示使用 IPv4 地址族。PF_INET是套接字编程中常用的地址族之一,用于创建基于 IPv4 的套接字。SOCK_STREAM:这个参数指定了套接字的类型,即套接字的通信方式。在这里,SOCK_STREAM表示创建一个流式套接字,它是一种可靠的、面向连接的、基于 TCP 协议的套接字。流式套接字提供了可靠的、双向的、面向字节的数据传输,适用于需要可靠数据传输的场景,如文件传输、视频流传输等。0:这个参数通常被称为协议参数,用于指定要使用的具体协议。在这里,由于我们使用的是SOCK_STREAM类型的套接字,所以传入0表示让系统自动选择使用默认的协议,即 TCP 协议。
2、调用bind函数分配IP地址和端口号
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
serv_addr.sin_family = AF_INET;设置套接字地址结构的地址族为AF_INET,表示使用 IPv4 地址族。serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);将套接字地址结构中的 IPv4 地址设置为INADDR_ANY。INADDR_ANY是一个特殊的 IPv4 地址常量,表示接受来自任意网络接口的连接请求。htonl()函数用于将主机字节序转换为网络字节序,因为sin_addr.s_addr是以网络字节序存储的。serv_addr.sin_port = htons(atoi(argv[1]));将套接字地址结构中的端口号设置为命令行参数argv[1]中指定的端口号。argv[1]是一个字符串,需要通过atoi()函数将其转换为整数形式,然后再使用htons()函数将端口号转换为网络字节序,因为sin_port是以网络字节序存储的。
这段代码的作用是将服务器套接字地址结构 serv_addr 初始化为一个特定的值,以便后续在代码中使用该地址结构绑定到服务器套接字上,从而指定服务器监听的地址和端口。
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
这行代码调用了 bind() 函数,将服务器套接字 serv_sock 绑定到指定的地址上。
bind()函数用于将一个套接字绑定到一个特定的地址和端口上。serv_sock是要绑定的套接字,即服务器套接字。(struct sockaddr*)&serv_addr将服务器套接字地址结构serv_addr强制转换为struct sockaddr*类型的指针,这是因为bind()函数接受的地址参数类型为struct sockaddr*。sizeof(serv_addr)给出了套接字地址结构的大小,即要绑定的地址结构的字节数。
3、调用listen函数转换为可接受请求状态
listen(serv_sock, 5);
这行代码调用了 listen() 函数,用于设置服务器套接字 serv_sock 开始监听客户端的连接请求。
listen()函数用于将一个套接字设置为被动模式,开始监听客户端的连接请求。serv_sock是要监听的服务器套接字。5是一个参数,表示服务器套接字的连接队列的长度。连接队列用于存放等待被服务器接受的客户端连接请求。如果连接队列已满,新的连接请求将被拒绝。通常情况下,这个参数的值会根据实际需要来设定,通常取值为 5 或 10。
4、调用accept函数受理连接请求
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
这段代码调用了 accept() 函数,用于接受客户端的连接请求,并创建一个新的套接字 clnt_sock 用于与客户端进行通信。
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);- 这行代码调用了
accept()函数,接受客户端的连接请求,并创建一个新的套接字clnt_sock用于与客户端进行通信。 serv_sock是服务器套接字,用于监听客户端的连接请求。(struct sockaddr*)&clnt_addr是一个指向客户端地址结构的指针,clnt_addr是用于存储客户端地址信息的变量。accept()函数将会把客户端的地址信息填充到clnt_addr中。&clnt_addr_size是一个指向整数的指针,用于传递客户端地址结构的大小给accept()函数。在函数调用完成后,clnt_addr_size将被更新为客户端地址结构的实际大小。
- 这行代码调用了
通过这段代码,服务器将会阻塞等待客户端的连接请求。一旦有客户端连接进来,accept() 函数将会返回一个新的套接字 clnt_sock,用于与客户端进行通信,并且客户端的地址信息将会填充到 clnt_addr 中。
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>int main(int argc, char *argv[]) {int serv_sock;int clnt_sock;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_size;char msg[] = "Hello world!\n";serv_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(argv[1]));bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));listen(serv_sock, 5);clnt_addr_size = sizeof(clnt_addr);clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);write(clnt_sock, msg, sizeof(msg));close(clnt_sock);close(serv_sock);return 0;
}
客户端创建套接字
客户端的套接字只有创建和发送连接请求两个步骤
1、调用socket函数创建套接字
2、调用connect函数向服务器端发送连接请求
(创建socket前边已经介绍,这里只介绍connect函数)
2、调用connect函数向服务器端发送连接请求
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
sock 是客户端套接字,即客户端用于与服务器通信的套接字。
(struct sockaddr*)&serv_addr 是指向服务器地址结构的指针,即服务器的地址信息。
sizeof(serv_addr) 给出了服务器地址结构的大小,即要连接的地址结构的字节数。
通过调用 connect() 函数,客户端套接字 sock 将会尝试连接到指定的服务器地址 serv_addr 上。如果连接成功,客户端将会与服务器建立起连接,可以进行数据交换。如果连接失败,则通常会返回一个错误码,表示连接过程中出现了问题。
需要注意的是,connect() 函数通常会阻塞等待,直到连接成功建立或者连接过程中出现错误。因此,如果需要非阻塞地发起连接,可以使用非阻塞的套接字操作或者使用多线程/多进程技术。
完整程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>int main(int argc, char *argv[]) {int sock;struct sockaddr_in serv_addr;char msg[30];int str_len;sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));read(sock, msg, sizeof(msg) - 1);printf("%s", msg);close(sock);return 0;
}
打开两个终端,分别编译和运行服务器端程序和客户端程序
# 先编译和运行服务器端
gcc hello_server.c -o hserver
./hserver 10087 # 端口号随便填,但是两边要一致# 然后编译运行客户端
gcc hello_client.c -o hclient
./hclient 127.0.0.1 10087 # 端口号随便填,但是两边要一致
运行完客户端的程序,就能看到打印 Hello world!了。
相关文章:
【网络编程】实现服务器端和客户端的通讯的简单程序
套接字是什么? 服务端接受连接请求的套接字创建过程可分为以下4步: 1、调用socket创建套接字 2、调用bind函数分配IP地址和端口号 3、调用listen函数转换为可接受请求状态 4、调用accept函数受理连接请求 1、调用socket创建套接字 serv_sock soc…...
如何在Portainer中部署Nginx容器并制作一个本地站点结合cpolar发布至公网可访问
文章目录 前言1. 安装Portainer1.1 访问Portainer Web界面 2. 使用Portainer创建Nginx容器3. 将Web静态站点实现公网访问4. 配置Web站点公网访问地址4.1公网访问Web站点 5. 固定Web静态站点公网地址6. 固定公网地址访问Web静态站点 前言 Portainer是一个开源的Docker轻量级可视…...
Mysql的储存引擎
储存引擎介绍 1. 文件系统 操作系统存取数据的一种机制 2. 文件系统类型 不管使用什么文件系统,数据内容不会变化 不同的是,存储空间、大小、速度 3. MySQL存储引擎 可以理解为,MySQL的“文件系统”,只不过功能更加强大 4. MySQL…...
【查漏补缺你的Vue基础】Vue数据监听深度解析
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
大语言模型LLM发展历程中的里程碑项目:国内外技术革新重塑自然语言处理(LLM系列02)
文章目录 标题:大语言模型LLM发展历程中的里程碑项目:国内外技术革新重塑自然语言处理(LLM系列02) 引言早期奠基阶段Transformer架构引领变革GPT系列的重大进展国内外标志性LLM项目LLM在中国的应用实践LLM研究面临的挑战与应对策略…...
JS二进制文件转换:File、Blob、Base64、ArrayBuffer
类型转换 1. Blob、File → Base64 function fileToDataURL(file) {let reader new FileReader();reader.readAsDataURL(file);reader.onload function (e) {return reader.result;}; }2. Base64 → Blob、File // Base64 转为 Blob function dataURLToBlob(fileDataURL) …...
编译opencv gpu版的条件
一、具备以下条件即可编译opencv gpu: 1、 终端设备必须有独立显卡。cmd窗口:nvidia-smi查看显卡信息 2、下载并安装CUDA Toolkit(根据显卡下载对应的CUDA Toolkit软件)、cuDNN(根据CUDA版本下载对应的cuDNN࿰…...
List集合的Stream流式操作实现数据类型转换
问题现象: 最近在项目中,有一些逻辑想用List集合的Stream流式操作来快速实现,但由于之前没做好学习笔记和总结,导致一时间想不起来,只能用本方法来解决,如下: 可以看出来代码量是比较冗长的&…...
Ubuntu 20.04.6 LTS下edge浏览器点击图标没反应
1.网上的解决方案 解决Ubuntu系统下启动root账户后Linux版本edge浏览器无法启动等 2.采用的解决方案 之前我一直是在官网下载 Microsoft Edge下载,安装,卸载,重装的stable版本,然后安装,始终没有效果。 最后利用Linux…...
php基础学习之错误处理(其一)
一,错误处理的概念 错误处理指的是系统(或者用户)在执行某些代码的时候,发现有错误,就会通过错误处理的形式告知程序员,俗称报错 二,错误分类 语法错误:书写的代码不符合 PHP 的语法规范,语法错…...
Nginx 解析漏洞复现
环境搭建 下载之后上传到虚拟机并解压 进入这个路径 (root?kali)-[~/vulhub-master/nginx/nginx_parsing_vulnerability]就能看到有docker-compose.yml 启动环境 正常显示 增加/.php后缀,被解析成PHP文件: 漏洞原因:开启了cgi.fix_pathin…...
JQMobile Loader Widget 遮罩层改造
最近在用jqmobile 做一个混合APP项目时候用到 jqmobile1.4.3提供的Loader Widget控件,但是这个控件本身是一个loading弹出层,这个弹出层弹出之后,用户还是可以去点击按钮,重复发送请求,为了防止重复提交,我想了两种办法, 1,在loading弹出层弹出之后,让按钮不可用.但是form表单…...
练习 2 Web [ACTF2020 新生赛]BackupFile 1
[ACTF2020 新生赛]BackupFile 1 Web常规题目 首先尝试查找常见的前端页面index.php之类的,没找到 题目有个“BackupFile”——备份文件 尝试用工具遍历查找相关的文件 御剑没扫出来,搜索搭建好dirsearch后,扫出来的index.php.bak 扫描工…...
【python】subprocess用法示例
当然,下面是一些使用 Python subprocess 模块的示例: 1. 运行命令并捕获输出 import subprocess # 运行 ls 命令并捕获输出 result subprocess.run([ls, -l], stdoutsubprocess.PIPE, stderrsubprocess.PIPE, textTrue) # 获取命令的输出和错误信息 o…...
Socket网络编程(三)——TCP快速入门
目录 概述TCP连接可靠性1. 三次握手过程2. 四次挥手过程3. 为什么挥手需要四次? 传输可靠性TCP核心APITCP传输初始化配置&建立连接客户端创建Socket建立连接服务端创建ServerSocket监听连接ServerSocket 和 Socket的关系 Socket基本数据类型传输客户端数据传输服…...
皇冠测评:网络电视盒子哪个品牌好?电视盒子排行榜
欢迎各位来到我们的测评频道,本期我们要分享的产品是电视盒子,因很多网友留言不知道网络电视盒子哪个品牌好,我们通过为期一个月的测评后整理了电视盒子排行榜,想买电视盒子的可以看看下面这五款产品,它们各方面表现非…...
simple-pytest 框架使用指南
simple-pytest 框架使用指南 一、框架介绍简介框架理念:框架地址 二、实现功能三、目录结构四、依赖库五、启动方式六、使用教程1、快速开始1.1、创建用例:1.2、生成py文件1.3、运行脚本1.3.1 单个脚本运行1.3.2 全部运行 1.4 报告查看 2、功能介绍2.1、…...
React中使用useActive
1.引入 import { useActivate } from "react-activation";2.React Activation 在React中使用react-activation,其实就是类似于Vue中的keep-alive,实现数据的缓存; 源码: import { ReactNode, ReactNodeArray, Context, Component…...
ElasticSearch安装和kibana控制台安装
文章目录 简介ElasticSearch安装环境下载参数密码配置启动 kibana安装修改config/kibana.yml配置 简介 Elasticsearch 是一个分布式文档存储。Elasticsearch 是存储已序列化为 JSON 文档的复杂数据结构。当集群中有多个 Elasticsearch 节点时,存储的文档分布在整个…...
VSCode安装与使用详细教程
一、引言 简要介绍VSCode(Visual Studio Code)是什么,它的主要特点和用途,以及为什么选择VSCode作为代码编辑器。 二、下载与安装 访问VSCode官方网站下载页面。选择适合操作系统的版本(Windows、macOS、Linux&…...
【技术解析】SwAV:用在线聚类与最优运输破解无监督视觉特征学习难题
1. SwAV:无监督视觉特征学习的破局者 想象一下你面前有100万张没有标签的图片,现在需要让AI自动学会识别其中的物体特征——这就是SwAV要解决的核心问题。传统方法就像让一个孩子通过反复对比无数相似图片来学习,不仅效率低下,还特…...
比迪丽LoRA模型企业内网部署方案:安全高效的内部AI绘画平台搭建
比迪丽LoRA模型企业内网部署方案:安全高效的内部AI绘画平台搭建 最近和几个在金融、设计公司做IT的朋友聊天,他们都在头疼同一个问题:团队想用AI绘画工具提升效率,比如快速生成营销素材、设计概念图,但直接把数据传到…...
GHelper:如何用10MB替代华硕官方控制中心,实现极致轻量化的硬件掌控
GHelper:如何用10MB替代华硕官方控制中心,实现极致轻量化的硬件掌控 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyr…...
C++ deprecated 关键字的实战指南:从标记到迁移的最佳实践
1. 理解C deprecated关键字的核心价值 第一次在代码里看到[[deprecated]]标记时,我正接手一个遗留的金融交易系统。那个满是警告的编译输出让我意识到,这个看似简单的属性其实是代码演化的时间胶囊。deprecated不是简单的"不要用"标签…...
PTPX功耗分析模式怎么选?Averaged vs. Time-Based模式深度对比与选型指南
PTPX功耗分析模式实战选型:从原理到决策的完整指南 芯片设计就像一场精心策划的能源管理艺术展,而PTPX则是我们手中那支精准的画笔。当设计进入纳米级工艺节点,功耗分析不再是锦上添花,而是决定芯片成败的关键环节。面对Averaged…...
终极免费时钟应用:Simple Clock如何帮你告别混乱,轻松管理每一天?[特殊字符]
终极免费时钟应用:Simple Clock如何帮你告别混乱,轻松管理每一天?🚀 【免费下载链接】Simple-Clock Combination of a beautiful clock with widget, alarm, stopwatch & timer, no ads 项目地址: https://gitcode.com/gh_m…...
Nacos注册中心实战:Java项目中的服务发现与管理
Nacos注册中心实战:Java项目中的服务发现与管理 前言 随着微服务架构的广泛应用,服务的高效注册与动态发现成为分布式系统的基础设施建设重点。Nacos 作为一款易用且功能强大的注册中心和配置中心,为 Java 项目提供了灵活的服务治理能力。本…...
Abaqus响应谱分析避坑指南:如何用模态动态法验证发动机悬置冲击结果?
Abaqus响应谱分析实战:模态动态法验证发动机悬置冲击结果的三大关键步骤 汽车发动机悬置系统的冲击仿真一直是CAE工程师的痛点领域。当你在凌晨三点盯着屏幕上两组截然不同的仿真结果时——响应谱法给出的峰值应力比模态动态法高出40%,该相信哪个&#x…...
2025_NIPS_RAGRouter: Learning to Route Queries to Multiple Retrieval-Augmented Language Models
文章主要内容总结 该研究聚焦检索增强生成(RAG)场景下的大语言模型(LLM)路由问题,提出了首个RAG感知的路由框架RAGRouter。核心解决现有路由方法依赖静态参数知识、忽略检索文档动态影响的缺陷,通过融合文档嵌入、RAG能力嵌入与对比学习,捕捉RAG引发的模型知识表征变化…...
2025届学术党必备的十大AI辅助论文工具解析与推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 基于大语言模型的智能写作辅助系统,是专为学术研究者设计的AI开题报告工具&#…...
