Linux基础网络编程-Socket通信

2024-09-05 16:52

本文主要是介绍Linux基础网络编程-Socket通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文使用C语言,在Centos实现Socket两种通信类型(TCP和UDP)

文章目录

  • 一、安装gcc
  • 二、使用TCP协议,实现Socket(SOCKE_STREAM)流式通信
    • 1. 编写`TCP_server.c`
      • 函数和参数解释
    • 2.编写`TCP_client.c`
      • 函数和参数解释
    • 3. 编译并运行上述两个文件
      • 3.1 编译
      • 3.2 运行(启动两个终端,分别运行)
      • 测试
  • 三、使用数据报协议UDP,实现数据报socket(SOCK_DGRAM)通信
    • 1. 编写`UDP_server.c`
      • 函数和参数解释
    • 2.编写`UDP_client.c`
      • 函数和参数解释
    • 3.编译运行及测试,参考TCP即可

一、安装gcc

如果Centos没有C语言编译器,使用下面命令进行下载安装

yum -y install gcc

使用下列命令查看安装版本

gcc --version

如安装失败,请寻找其他教程

二、使用TCP协议,实现Socket(SOCKE_STREAM)流式通信

1. 编写TCP_server.c

#include <sys/types.h>  // 包含基本系统数据类型
#include <sys/socket.h> // 包含socket函数及数据结构
#include <netinet/in.h> // 定义数据结构sockaddr_in
#include <arpa/inet.h>  // 提供IP地址转换函数
#include <string.h>     // 提供字符串处理函数
#include <stdlib.h>     // 提供通用工具函数
#include <stdio.h>      // 提供输入输出函数
#include <unistd.h>     // 提供对POSIX操作系统API的访问功能#define QUEUE 20        // 最大同时连接请求数
#define BUFFER_SIZE 1024 // 缓冲区大小int main()
{// 创建socket,指定IPv4协议族,流式socketint server_sockfd = socket(AF_INET, SOCK_STREAM, 0);// 定义服务器地址结构struct sockaddr_in server_sockaddr;server_sockaddr.sin_family = AF_INET; // 地址族server_sockaddr.sin_port = htons(8887); // 端口号,使用htons进行字节序转换server_sockaddr.sin_addr.s_addr = inet_addr("192.168.138.133"); // 服务器IP地址// 绑定socketif(bind(server_sockfd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr)) == -1){perror("bind"); // 如果绑定失败,打印错误信息exit(1); // 退出程序}// 监听网络连接if(listen(server_sockfd, QUEUE) == -1){perror("listen"); // 如果监听失败,打印错误信息exit(1); // 退出程序}// 定义客户端地址结构char buffer[BUFFER_SIZE];struct sockaddr_in client_addr;socklen_t length = sizeof(client_addr);// 接受客户端连接int conn = accept(server_sockfd, (struct sockaddr *)&client_addr, &length);if(conn < 0){perror("connect"); // 如果连接失败,打印错误信息exit(1); // 退出程序}// 数据交换循环while(1){memset(buffer, 0, sizeof(buffer)); // 清空缓冲区int len = recv(conn, buffer, sizeof(buffer), 0); // 接收数据if(strcmp(buffer, "exit\n") == 0) // 如果接收到"exit"命令,则退出循环break;fputs(buffer,{"code":504,"success":false,"message":"Gateway timeout has occurred"} stdout); // 将接收到的数据打印到标准输出send(conn, buffer, len, 0); // 将接收到的数据发送回客户端}// 关闭连接close(conn);close(server_sockfd);return 0;
}

函数和参数解释

  • socket(int domain, int type, int protocol): 创建一个新的socket。

    • domain: 指定协议族,这里是AF_INET(IPv4网络协议)。
    • type: 指定socket类型,这里是SOCK_STREAM(提供顺序化、可靠、双向的基于连接的字节流)。
    • protocol: 指定具体协议,0表示自动选择type对应的默认协议,这里是TCP。
  • bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen): 将socket绑定到本地地址。

    • sockfd: socket文件描述符。
    • addr: 指向本地地址信息的指针。
    • addrlen: 地址信息的长度。
  • listen(int sockfd, int backlog): 开始监听网络连接请求。

    • sockfd: socket文件描述符。
    • backlog: 最大同时连接请求数。
  • accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen): 接受一个连接请求。

    • sockfd: socket文件描述符。
    • addr: 指向客户端地址信息的指针。
    • addrlen: 地址信息的长度。
  • recv(int sockfd, void *buf, size_t len, int flags): 接收数据。

    • sockfd: 连接的socket文件描述符。
    • buf: 指向接收缓冲区的指针。
    • len: 缓冲区的长度。
    • flags: 传输控制标志,这里为0表示无特殊操作。
  • send(int sockfd, const void *buf, size_t len, int flags): 发送数据。

    • sockfd: 连接的socket文件描述符。
    • buf: 指向数据缓冲区的指针。
    • len: 要发送的数据字节数。
    • flags: 传输控制标志,这里为0表示无特殊操作。

这段代码首先创建一个服务器端的socket,然后绑定到本地地址和端口上,之后监听来自客户端的连接请求。一旦接受到连接请求,服务器就会进入一个循环,接收客户端发送的数据并将其回显给客户端,直到接收到"exit"命令为止。最后,关闭客户端和服务器的socket连接。

2.编写TCP_client.c

#include <sys/types.h>  // 包含基本系统数据类型
#include <sys/socket.h> // 包含socket函数及数据结构
#include <netinet/in.h> // 定义数据结构sockaddr_in
#include <arpa/inet.h>  // 提供IP地址转换函数
#include <string.h>     // 提供字符串处理函数
#include <stdlib.h>     // 提供通用工具函数
#include <stdio.h>      // 提供输入输出函数
#include <unistd.h>     // 提供对POSIX操作系统API的访问功能#define QUEUE 20        // 最大同时连接请求数
#define BUFFER_SIZE 1024 // 缓冲区大小int main()
{// 创建socket,指定IPv4协议族,流式socketint sock_cli = socket(AF_INET, SOCK_STREAM, 0);// 定义服务器地址结构struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr)); // 初始化地址结构servaddr.sin_family = AF_INET; // 地址族servaddr.sin_port = htons(8887); // 端口号,使用htons进行字节序转换servaddr.sin_addr.s_addr = inet_addr("192.168.138.133"); // 服务器IP地址// 连接服务器if(connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){perror("connect"); // 如果连接失败,打印错误信息exit(1); // 退出程序}char sendbuf[BUFFER_SIZE]; // 发送缓冲区char recvbuf[BUFFER_SIZE]; // 接收缓冲区// 数据交换循环while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){send(sock_cli, sendbuf, strlen(sendbuf), 0); // 发送数据if(strcmp(sendbuf, "exit\n") == 0) // 如果输入"exit"命令,则退出循环break;recv(sock_cli, recvbuf, sizeof(recvbuf), 0); // 接收数据fputs(recvbuf, stdout); // 将接收到的数据打印到标准输出memset(sendbuf, 0, sizeof(sendbuf)); // 清空发送缓冲区memset(recvbuf, 0, sizeof(recvbuf)); // 清空接收缓冲区}// 关闭socketclose(sock_cli);return 0;
}

函数和参数解释

  • socket(int domain, int type, int protocol): 创建一个新的socket。

    • domain: 指定协议族,这里是AF_INET(IPv4网络协议)。
    • type: 指定socket类型,这里是SOCK_STREAM(提供顺序化、可靠、双向的基于连接的字节流)。
    • protocol: 指定具体协议,0表示自动选择type对应的默认协议,这里是TCP。
  • connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen): 请求连接到指定的socket。

    • sockfd: socket文件描述符。
    • addr: 指向目标主机地址信息的指针。
    • addrlen: 地址信息的长度。
  • send(int sockfd, const void *buf, size_t len, int flags): 发送数据。

    • sockfd: socket文件描述符。
    • buf: 指向数据缓冲区的指针。
    • len: 要发送的数据字节数。
    • flags: 传输控制标志,这里为0表示无特殊操作。
  • recv(int sockfd, void *buf, size_t len, int flags): 接收数据。

    • sockfd: socket文件描述符。
    • buf: 指向接收缓冲区的指针。
    • len: 缓冲区的长度。
    • flags: 传输控制标志,这里为0表示无特殊操作。

这段代码首先创建一个客户端的socket,然后连接到服务器的指定IP地址和端口上。一旦连接成功,客户端就会进入一个循环,从标准输入读取数据发送到服务器,并接收服务器的回应,直到输入"exit"命令为止。最后,关闭socket连接。

3. 编译并运行上述两个文件

3.1 编译

gcc TCP_server.c -o TCP_server
gcc TCP_client.c -o TCP_client

3.2 运行(启动两个终端,分别运行)

./TCP_server
./TCP_client

启动成功后,如图所示:
在这里插入图片描述

测试

在client端输入test
在这里插入图片描述
按下回车,可以看到,server端收到test
在这里插入图片描述

三、使用数据报协议UDP,实现数据报socket(SOCK_DGRAM)通信

1. 编写UDP_server.c

#include <sys/types.h> // 包含系统数据类型定义
#include <sys/socket.h> // 提供socket函数及相关数据结构
#include <netinet/in.h> // 包含IP地址和端口号数据结构
#include <arpa/inet.h> // 提供IP地址转换函数
#include <string.h> // 提供字符串处理函数
#include <stdlib.h> // 提供标准库函数
#include <sys/shm.h> // 提供共享内存相关函数
#include <stdio.h> // 提供输入输出函数
#include <fcntl.h> // 提供文件控制函数
#include <unistd.h> // 提供POSIX操作系统API#define RECVLENTH 120 // 定义接收数据长度
#define SENDLENTH 120 // 定义发送数据长度int main(int argc, char **argv)
{int sockefd = socket(AF_INET, SOCK_DGRAM, 0); // 创建一个UDP socketif(sockefd == -1){perror("socket failed!"); // 输出错误信息}struct sockaddr_in saddr, caddr; // 定义服务器地址结构和客户端地址结构memset(&saddr, 0, sizeof(struct sockaddr_in)); // 初始化服务器地址结构saddr.sin_family = AF_INET; // 设置地址族为IPv4saddr.sin_port = htons(6666); // 设置端口号,使用htons进行字节序转换saddr.sin_addr.s_addr = inet_addr("192.168.138.133"); // 设置服务器IP地址int ret = bind(sockefd, (struct sockaddr*)&saddr, sizeof(struct sockaddr)); // 将socket绑定到服务器地址if(ret == -1){perror("bind failed!"); // 输出错误信息}char buf[RECVLENTH]; // 定义接收数据的缓冲区memset(buf, 0, RECVLENTH); // 初始化接收缓冲区int size = sizeof(struct sockaddr); // 获取地址结构的长度recvfrom(sockefd, buf, RECVLENTH, 0, (struct sockaddr*)&caddr, &size); // 接收客户端发送的数据printf("[server recv]:%s\n", buf); // 打印接收到的数据char buf1[SENDLENTH] = {"hello client!"}; // 准备要发送的数据sendto(sockefd, buf1, strlen(buf1), 0, (struct sockaddr*)&caddr, sizeof(struct sockaddr)); // 发送数据给客户端close(sockefd); // 关闭socket连接return 0;
}

函数和参数解释

  • socket(AF_INET, SOCK_DGRAM, 0): 创建一个UDP socket。

    • AF_INET: 指定协议族为IPv4。
    • SOCK_DGRAM: 指定socket类型为数据报套接字,即UDP。
    • 0: 传输协议,这里为默认值。
  • bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen): 将socket绑定到特定地址。

    • sockfd: socket文件描述符。
    • addr: 指向要绑定的地址结构的指针。
    • addrlen: 地址结构的长度。
  • recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen): 接收数据报。

    • sockfd: socket文件描述符。
    • buf: 接收数据的缓冲区。
    • len: 缓冲区长度。
    • flags: 接收标志,这里为0表示无特殊操作。
    • src_addr: 指向发送方地址结构的指针。
    • addrlen: 地址结构的长度。
  • sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen): 发送数据报。

    • sockfd: socket文件描述符。
    • buf: 要发送的数据。
    • len: 数据长度。
    • flags: 发送标志,这里为0表示无特殊操作。
    • dest_addr: 指向目标地址结构的指针。
    • addrlen: 地址结构的长度。

这段代码创建了一个UDP服务器端,绑定到特定地址和端口上。它接收来自客户端的数据报,然后回显"hello client!"给客户端,并关闭连接。

2.编写UDP_client.c

#include <sys/types.h> // 包含系统数据类型定义
#include <sys/socket.h> // 提供socket函数及相关数据结构
#include <netinet/in.h> // 包含IP地址和端口号数据结构
#include <arpa/inet.h> // 提供IP地址转换函数
#include <string.h> // 提供字符串处理函数
#include <stdlib.h> // 提供标准库函数
#include <sys/shm.h> // 提供共享内存相关函数
#include <stdio.h> // 提供输入输出函数
#include <fcntl.h> // 提供文件控制函数
#include <unistd.h> // 提供POSIX操作系统API#define RECVLENTH 120 // 定义接收数据的缓冲区大小
#define SENDLENTH 120 // 定义发送数据的缓冲区大小int main(int argc, char **argv) // 主函数入口,接收命令行参数
{int sockefd = socket(AF_INET, SOCK_DGRAM, 0); // 创建一个UDP socketif (sockefd == -1) // 检查socket是否创建成功{perror("socket failed!"); // 输出错误信息}struct sockaddr_in saddr, caddr; // 定义服务器地址结构和客户端地址结构memset(&saddr, 0, sizeof(struct sockaddr_in)); // 初始化服务器地址结构saddr.sin_family = AF_INET; // 设置地址族为IPv4saddr.sin_port = htons(6666); // 设置端口号,使用htons进行字节序转换saddr.sin_addr.s_addr = inet_addr("192.168.138.133"); // 设置服务器IP地址char buf[SENDLENTH] = "hello server"; // 准备要发送的数据sendto(sockefd, buf, strlen(buf), 0, (struct sockaddr*)&saddr, sizeof(struct sockaddr)); // 发送数据给服务器char buf1[RECVLENTH]; // 定义接收数据的缓冲区memset(buf1, 0, RECVLENTH); // 初始化接收缓冲区int size = sizeof(struct sockaddr); // 获取地址结构的长度recvfrom(sockefd, buf1, RECVLENTH, 0, (struct sockaddr*)&caddr, &size); // 接收服务器发送的数据printf("[client recv]:%s\n", buf1); // 打印接收到的数据close(sockefd); // 关闭socket连接return 0; // 返回程序执行成功
}

函数和参数解释

  • socket(AF_INET, SOCK_DGRAM, 0): 创建一个UDP socket。

    • AF_INET: 指定协议族为IPv4。
    • SOCK_DGRAM: 指定socket类型为数据报套接字,即UDP。
    • 0: 传输协议,这里为默认值。
  • bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen): 将socket绑定到特定地址。

    • sockfd: socket文件描述符。
    • addr: 指向要绑定的地址结构的指针。
    • addrlen: 地址结构的长度。
  • recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen): 接收数据报。

    • sockfd: socket文件描述符。
    • buf: 接收数据的缓冲区。
    • len: 缓冲区长度。
    • flags: 接收标志,这里为0表示无特殊操作。
    • src_addr: 指向发送方地址结构的指针。
    • addrlen: 地址结构的长度。
  • sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen): 发送数据报。

    • sockfd: socket文件描述符。
    • buf: 要发送的数据。
    • len: 数据长度。
    • flags: 发送标志,这里为0表示无特殊操作。
    • dest_addr: 指向目标地址结构的指针。
    • addrlen: 地址结构的长度。

这段代码创建了一个UDP客户端,向特定地址和端口发送"hello server",然后接收服务器端回复的数据并打印出来。

3.编译运行及测试,参考TCP即可





转载请注明出处
作者:BQ
主页:https://blog.csdn.net/weixin_52677672?type=blog
QQ群:958124241
Learn Together!

这篇关于Linux基础网络编程-Socket通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139527

相关文章

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~

poj 3068 有流量限制的最小费用网络流

题意: m条有向边连接了n个仓库,每条边都有一定费用。 将两种危险品从0运到n-1,除了起点和终点外,危险品不能放在一起,也不能走相同的路径。 求最小的费用是多少。 解析: 抽象出一个源点s一个汇点t,源点与0相连,费用为0,容量为2。 汇点与n - 1相连,费用为0,容量为2。 每条边之间也相连,费用为每条边的费用,容量为1。 建图完毕之后,求一条流量为2的最小费用流就行了