在Linux系统实现服务器端和客户端的套接字通信

news/2024/11/25 7:53:10/

目录

一.创建一个socket文件夹用来存放编写的服务器端和客户端程序

二.编写服务器端代码

三.编写客户端代码

四.编译c语言程序

五.断开连接

六.可能涉及到的一些没接触过的知识点

一.创建一个socket文件夹用来存放编写的服务器端和客户端程序

(我系统里的文件在temp/socket$文件夹中)

 

二.编写服务器端代码

vim server.c

在server.c中编写的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数int main()
{//1.创建监听的套接字int fd = socket(AF_INET,SOCK_STREAM, 0);if (fd == -1){perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。return -1;}//2.绑定本地的IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;//地址族协议saddr.sin_port = htons(9999);//端口必须转换成大端saddr.sin_addr.s_addr = INADDR_ANY;//指定IP地址(INADDR_ANY泛指本机的意思,也就是表示本机的所有IP)int ret = bind(fd, (struct sockaddr*)&saddr, sizeof(saddr));if (ret == -1)//绑定失败 返回-1{perror("bind");return -1;}//3设置监听ret = listen(fd, 128);if (ret == -1){perror("listen");return -1;}//4阻塞并等待客户端的连接struct sockaddr_in caddr;int addrlen = sizeof(caddr);int cfd = accept(fd, (struct sockaddr*)&caddr,&addrlen );if (cfd == -1){perror("accept");return -1;}//连接建立成功,打印客户端的IP和端口信息char ip[32];printf("客户端的ip:%s,端口:%d\n",inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(caddr.sin_port));//网络字节序转换为主机字节序//5.通信while (1){//接收数据char buff[1024];int len = recv(cfd, buff, sizeof(buff), 0);if (len > 0){printf("client say: %s\n", buff);send(cfd, buff, len, 0);}else if (len == 0){printf("客户端已经断开了连接...\n");break;}else{perror("recv");break;}}//关闭文件描述符close(fd);close(cfd);return 0;
}

三.编写客户端代码

vim client.c

在client中编写的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数int main()
{//1.创建通信的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1){perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。return -1;}//2.连接服务器IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;//地址族协议saddr.sin_port = htons(9999);//端口必须转换成大端inet_pton(AF_INET, "192.168.122.1 ", &saddr.sin_addr.s_addr);int ret = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));if (ret == -1)//连接失败 返回-1{perror("connect");return -1;}int number = 0;//3.通信while (1){//发送数据char buff[1024];sprintf(buff, "你好,hello ,world ,%d...\n", number++);send(fd, buff, strlen(buff) + 1, 0);//接收数据memset(buff, 0, sizeof(buff));int len = recv(fd, buff, sizeof(buff), 0);if (len > 0){printf("server say: %\n", buff);}else if (len == 0){printf("服务器端已经断开了连接...\n");break;}else{perror("recv");break;}sleep(1);}//关闭文件描述符close(fd);return 0;
}

四.编译c语言程序

[itliang@localhost socket]$ gcc client.c -o client
[itliang@localhost socket]$ gcc server.c -o server

 运行server.c程序,先运行服务器端再运行客户端

 运行client.c程序,至此客户端与服务器端建立通信,客户端收到服务器端消息,并输出“你好,hello,world”

 

 服务器端收到客户端消息,并输出“你好,hello,world”

 五.断开连接

当服务器端断开连接时,客户端会显示“服务器端已经断开了连接”

 当客户端断开连接时,服务器端会显示“客户端已经断开了连接”

 

 六.可能涉及到的一些没接触过的知识点

perror(s)函数

        用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。

sockaddr_in在头文件#include<netinet/in.h>或#include <arpa/inet.h>中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中,如下:

 

GCC 是 Linux 下的编译工具集,是 GNU Compiler Collection 的缩写,包含 gcc、g++ 等编译器。这个工具集不仅包含编译器,还包含其他工具集,例如 ar、nm 等。

        GCC 工具集不仅能编译 C/C++ 语言,其他例如 Objective-C、Pascal、Fortran、Java、Ada 等语言均能进行编译。GCC 在可以根据不同的硬件平台进行编译,即能进行交叉编译,在 A 平台上编译 B 平台的程序,支持常见的 X86、ARM、PowerPC、mips 等,以及 Linux、Windows 等软件平台。
        有些纯净版的 Linux 默认没有 gcc 编译器,需要自己安装,在线安装步骤如下:

# 安装软件必须要有管理员权限
# ubuntu
$ sudo apt update           # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo apt install gcc g++    # 通过下载列表中提供的地址下载安装包, 并安装# centos
$ sudo yum update           # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo yum install gcc g++    # 通过下载列表中提供的地址下载安装包, 并安装
gcc 安装完毕之后,可以查看版本:# 查看 gcc 版本
$ gcc -v
$ gcc --version# 查看 g++ 版本
$ g++ -v
$ g++ --version

编译:

# 参数 -c 是进行文件的汇编, 汇编之前的两步会自动执行
$ gcc test.c -c -o app.o


http://www.ppmy.cn/news/108643.html

相关文章

【多线程】sleep( ) 和 wait( ) 区别面试常问到

文章目录 前言区别1&#xff1a;使用限制区别2&#xff1a;使用场景区别3&#xff1a;所属类区别4&#xff1a;释放锁区别5&#xff1a;线程切换 前言 sleep(休眠) 和 wait(等待) 方法是 Java 多线程中常用的两个方法&#xff0c;它们有什么区别及一些该注意的地方有哪些呢&am…

Django_models模型--03

1. 配置MySQL表&#x1f415;&#x1f415;&#x1f415; 1.1 安装mysql&#x1f405;&#x1f405; MySQL Workbench 8.0 CE 1.2 MySQL驱动&#x1f408;&#x1f408; 1.21 使用mysqlclient&#x1f406; 使用mysqlclientpip install mysqlclient( 如果上面的命令安装失…

2023年春秋杯网络安全联赛春季赛Reverse题目复现

文章目录 一.sum1. 分析程序逻辑2.解数独矩阵3.解题脚本 二.Poisoned_tea_CHELL1. 重新识别函数及程序逻辑分析2.IDA动态调试(attach附加调试)3. 输入选项进行单步调试4.解题脚本 一.sum 1. 分析程序逻辑 这里直接贴上当时分析的结果,根据程序行为不难猜出是数独问题(还得靠猜…

MATLAB 之 数值数据,矩阵的表示和变量及其操作

文章目录 一、数值数据1. 数值数据类型的分类1.1 整型1.2 浮点型1.3 复型 2. 数据的输出格式 二、矩阵的表示1. 矩阵的建立1.1 直接输入法建立矩阵1.2 已建好的矩阵建立更大的矩阵 2. 冒号表达式3. 矩阵元素的引用3.1 矩阵元素的引用方式3.2 利用冒号表达式获得子矩阵3.3 利用空…

【python技能树】python简介

1 Python定义 Python 是一种简单易学并且结合了解释性、编译性、互动性和面向对象的脚本语言。Python提供了高级数据结构&#xff0c;它的语法和动态类型以及解释性使它成为广大开发者的首选编程语言。 Python 是解释型语言&#xff1a; 开发过程中没有了编译这个环节。类似于…

Python中Pandas库中的DataFrame数据结构创建举例

Python中Pandas库的DataFrame数据结构创建举例 DataFrame的数据结构是Python数据分析中重要应用数据类型。本文将重点介绍DataFrame的创建。 1.DataFrame的创建 创建DataFrame的方法使用pandas.DataFrame&#xff0c;向该方法传入字典即可创建DataFrame。 传入的字典的key对应E…

针对vue的v-model绑定的props对象,组件值修改视图不更新粗暴解决方案。

文章目录 一、故事背景二、需求改造三、粗暴的解决方案 一、故事背景 接手组里同事写的代码&#xff0c;发现组件逻辑是这么写的 父组件引用子组件子组件定义了props属性paramsObject是一个数组&#xff0c;用于子组件的UI组件的循环逻辑。子组件的UI&#xff0c;v-model绑定pa…

《算法导论》拓展之 一维二维最近点对问题

一维点对问题 描述&#xff1a;一维最近点对问题是指在给定的一维点集中找到距离最近的两个点。具体来说&#xff0c;给定一维坐标轴上的 n 个点&#xff0c;要找出其中的两个点&#xff0c;使它们的距离最小。 解决办法&#xff1a;解决这个问题的一种常见方法是使用排序和线…