【北京迅为】iTOP-4412全能版使用手册-第三十二章 网络通信-TCP套字节

iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、陀螺仪、CAN总线、RS485总线、500万摄像头等模块,稳定运行Android 4.0.3/Android 4.4操作,系统通用Linux-3.0.15+Qt操作系统(QT支持5.7版本),Ubuntu版本:12.04,接口智能分配 方便好用。


第三十二章 网络通信-TCP套字节

在 Linux 下,网络资源非常丰富,底层的东西不需要去管,只需要知道怎么实现最终需要的功能即可。

本章配套视频为:

“视频 18 网络通信-套字节 TCP”

32.1 TCP通信简介

本节来学习一下 linux 网络通信程序的编写,使用的硬件平台是 iTOP-4412 开发板。TCP 是一种面向连接的、可靠的、基于 IP 的传输层协议。通过 TCP 可以保证传送的数据的正确性。

Linux 下网络通信程序基本上都是采用 socket 的方式。socket 起源于 Unix,而Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开 open->读写 read/write-> 关闭 close”模式来操作。Socket 就是该模式的一个实现,socket 即是一种特殊的文件,一些 socket 函数就是对其进行的操作(读/写 IO、打开、关闭)。说白了 socket 是应用程序与TCP/IP 协议族通信的中间软件抽象层,它是一组接口。

现在看一下基于 TCP/IP 应用程序通信的流程,如下图。

通过上图可以看到 TCP/IP 通信是基于服务器/客户端的模式来实现的,首先是服务器(server)端调用 socket 函数创建一个套接字,然后调用 bind 绑定函数,绑定函数主要是设置通信时使用哪种地址族(IPv4,IPv6 等),使用的端口号。然后调用 listen 函数来监听客户端的连接请求。

现在来看下客户端(client)端的流程,首先调用 socket 函数创建一个套接字,然后调用 connect 函数连接服务器,这时服务器端的 listen 函数监听到客户端的连接请求就会调用accept 函数去接受请求,这样连接就建立好了。之后双方就可以调用 read/write 函数收发数据了,在完成通信以后服务器(server)和客户端(client)调用 close 函数关闭创建的套接字。

32.2 服务器程序

下面来看一个实现 TCP/IP 的通信的例子,首先来看一下服务器(server)端的代码:

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>int main()
{int sfp, nfp, num = 0;struct sockaddr_in s_add,c_add;int sin_size;unsigned short portnum=0x8888;char buffer[100] = {0};printf("Hello,welcome to my server !\r\n");/* 创建 TCP 连接的套接字 */sfp = socket(AF_INET, SOCK_STREAM, 0);if(-1 == sfp){printf("socket fail ! \r\n");return -1;}printf("socket ok !\r\n");/* 变量 s_add 清零 */bzero(&s_add,sizeof(struct sockaddr_in));s_add.sin_family=AF_INET;s_add.sin_addr.s_addr=htonl(INADDR_ANY);s_add.sin_port=htons(portnum);/* 绑定 s_add 到套接字 sfp 上 */if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))){printf("bind fail !\r\n");return -1;}printf("bind ok !\r\n");/*监听函数,静听客户端的连接请求 */if(-1 == listen(sfp,5)){printf("listen fail !\r\n");return -1;}printf("listen ok\r\n")sin_size = sizeof(struct sockaddr_in);/* 接受连接请求 */nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);if(-1 == nfp){printf("accept fail !\r\n");return -1;}printf("accept ok!\r\nServer start get connect from %#x : %#x\r\n", ntohl(c_add.sin_addr.s_addr), ntohs(c_add.sin_port));while(1){memset(buffer, 0, 100);sprintf(buffer, "hello,welcome to my server(%d) \r\n", num++);/* 发送函数 */send(nfp, buffer, strlen(buffer), 0);usleep(500000);}/* 关闭 socket 连接 */close(nfp);/* 关闭 socket 连接 */close(sfp);return 0;
}

程序首先是包含一些需要用到的头文件,然后是 main 主函数,在 main 函数里面首先是定义了一些变量,然后调用 socket 函数创建一个套接字,socket 函数的第二个参数是SOCK_STREAM,表示创建的是 TCP 连接。然后调用 bzero 函数把变量 s_add 清零,然后给s_add 结构里面的变量赋值:

s_add.sin_family=AF_INET;//使用 IPv4 协议

s_add.sin_addr.s_addr=htonl(INADDR_ANY);//允许任何地址

s_add.sin_port=htons(portnum);//设置端口号

然后调用 bind 绑定函数,使用的是 IPv4 协议族,然后调用 listen 监听函数,监听用户

的连接请求。在监听到用户的请求后调用 accept 函数接受请求,然后进入到循环发送的代码,会循环发送“hello,welcome to my server”+发送次数号,最后会调用 close 关闭套接字。

32.3 客户端程序

下面来看看客户端(client)端的代码:

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>int main(int argc, char **argv)
{int cfd;int recbyte;int sin_size;char buffer[1024] = {0};struct sockaddr_in s_add, c_add;unsigned short portnum = 0x8888;printf("Hello,welcome to client!\r\n");if(argc != 2){printf("usage: echo ip\n");return -1;}/* 创建一个 TCP 连接的 socket */cfd = socket(AF_INET, SOCK_STREAM, 0);if(-1 == cfd){printf("socket fail ! \r\n");return -1;}printf("socket ok !\r\n");/* 变量 s_add 清零 */bzero(&s_add,sizeof(struct sockaddr_in));s_add.sin_family=AF_INET;s_add.sin_addr.s_addr= inet_addr(argv[1]);s_add.sin_port=htons(portnum);printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);/* 连接服务器函数 */if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))){printf("connect fail !\r\n");return -1;}printf("connect ok !\r\n");while(1){/* 接收服务器发过来的数据 */if(-1 == (recbyte = read(cfd, buffer, 1024))){printf("read data fail !\r\n");return -1;}printf("read ok\r\nREC:\r\n");buffer[recbyte]='\0';printf("%s\r\n",buffer);}/* 关闭套接字 */close(cfd);return 0;
}

首先是包含一些需要的头文件,然后进入 main 主函数定义了一些变量,然后调用socket 函数创建套接字,然后调用 bzero 函数把变量 s_add 清零,然后给 s_add 结构里面的变量赋值:

s_add.sin_family=AF_INET;//使用 IPv4 协议

s_add.sin_addr.s_addr= inet_addr(argv[1]);//设置要连接的 IP 地址(这里是执行程序的时候传递进来的)

s_add.sin_port=htons(portnum);//设置端口号

然后调用 connect 函数来连接服务器(server),在连接成功后,就进入了循环接收函数,使用 read 函数接收服务器发送的数据。最后会调用 close 函数关闭套接字。

32.4 编译测试

下面来编译下这两个程序,服务器(server)的程序运行在虚拟机 Ubuntu 上,所以使用下面的命令编译:

gcc -o server server.c

这样就生成了 server 可执行文件,客户端(client)的程序运行在 iTOP-4412 开发板上,使用下面的命令编译:

arm-none-linux-gnueabi-gcc -o client client.c

这样就生成了 client 可执行程序,把 client 下载到 iTOP-4412 开发板上,现在开始运行这两个程序,首先在虚拟机 Ubuntu 上运行 serevr 程序,如下图。

 

可以看到 server 打印出来的运行信息,现在 server 运行到了 listen 函数开始监听客户端的连接。下面在 iTOP-4412 开发板上运行 client 程序(因为我把 client 下载到了/bin 目录下,所以先进入到/bin 目录)执行下面的命令:

./client 192.168.1.77

上面命令里面的 192.168.1.77 是虚拟机 Ubuntu 的 IP 地址,看到程序连接成功,首先看一下虚拟机 Ubuntu 上的 server 打出的信息,如下图。

 

可以看到上图中 server 打印出了客户端的 ip 地址和端口号“Server start get connect from 0xc0a801e6 : 0xe171”。

然后看一下 iTOP-4412 开发板串口的打印信息,如下图。

通过上图可以看到打印连接成功“connect ok !”,然后串口会一直打印

read ok REC:

hello,welcome to my server(0)

至此,基于 TCP/IP 的 socket 网络编程就已经完成了。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript(JS)的对象

目录 1.array 数组对象 2.String 字符串对象 3.JSON 对象&#xff08;数据载体&#xff0c;进行数据传输&#xff09; 4.BOM 浏览器对象 5.DOM 文档对象&#xff08;了解&#xff09; 1.array 数组对象 定义方式1&#xff1a;var 变量名 new Array(元素列表); 定义方式…

Cannot resolve symbol ‘ActivityThread‘ | Android 语法

背景 ActivityThread 是 Android 系统内部使用的一个类,它位于 android.app 包中,但在 Android SDK 的公共 API 中并没有公开。 由于 ActivityThread 是隐藏的内部类,因此在编写单元测试或功能开发时,无法直接引用它。可以使用反射来访问内部 API,或者使用依赖注入的方式…

AI论文速读 | TimeXer:让 Transformer能够利用外部变量进行时间序列预测

题目&#xff1a; TimeXer: Empowering Transformers for Time Series Forecasting with Exogenous Variables 作者&#xff1a;Yuxuan Wang ; Haixu Wu&#xff08;吴海旭&#xff09; ; Jiaxiang Dong ; Yong Liu ; Yunzhong Qiu ; Haoran Zhang ; Jianmin Wang&#xff08;…

Zustand的学习和应用

Zustand 是一个轻量级的状态管理库&#xff0c;适用于 React 应用程序。它以简单易用、高性能和无模板代码的特性受到开发者的喜爱。 https://zustand.docs.pmnd.rs/guides/tutorial-tic-tac-toe 以下是 Zustand 的核心特点和用法简介&#xff1a; Zustand 核心特点 轻量简…

【从零开始的LeetCode-算法】3274. 检查棋盘方格颜色是否相同

给你两个字符串 coordinate1 和 coordinate2&#xff0c;代表 8 x 8 国际象棋棋盘上的两个方格的坐标。 以下是棋盘的参考图 如果这两个方格颜色相同&#xff0c;返回 true&#xff0c;否则返回 false。 坐标总是表示有效的棋盘方格。坐标的格式总是先字母&#xff08;表示列…

常见问题QA的前端代码

这个的后端代码参见此文 使用语言向量建立常见问题的模糊搜索-CSDN博客https://blog.csdn.net/chenchihwen/article/details/144207262?spm1001.2014.3001.5501 这段代码实现了一个简单的问答页面&#xff0c;页面分为左右两部分&#xff0c;左侧用于展示对话记录&#xff0c…

互联网 Java 面试八股文汇总(2025 最新整理)

我分享的这份 Java 后端开发面试总结包含了 JavaOOP、Java 集合容器、Java 异常、并发编程、Java 反射、Java 序列化、JVM、Redis、Spring MVC、MyBatis、MySQL 数据库、消息中间件 MQ、Dubbo、Linux、ZooKeeper、 分布式 &数据结构与算法等 25 个专题技术点&#xff0c;都…

CTF之密码学(密码特征分析)

一.MD5,sha1,HMAC,NTLM 1.MD5&#xff1a;MD5一般由32/16位的数字(0-9)和字母(a-f)组成的字符串 2.sha1&#xff1a;这种加密的密文特征跟MD5差不多&#xff0c;只不过位数是40&#xff08;sha256&#xff1a;64位&#xff1b;sha512:128位&#xff09; 3.HMAC&#xff1a;这…

Linux 入门——基本指令2

目录 1. 通配符的使用 1&#xff09;基本使用 2&#xff09; 拓展使用 2. cp 文件拷贝 基本使用 3. mv :文件剪切或者文件重命名 4. more 指令 5. less 指令 6. cat ,more , less 指令的区别 7. head 8. tail 9. date 日期&#xff0c;时间相关的指令 1&…

2024年12月3日Github流行趋势

项目名称&#xff1a;Lobe Chat 项目维护者&#xff1a;arvinxx, semantic-release-bot, canisminor1990, lobehubbot, renovate项目介绍&#xff1a;一个开源的、现代化设计的人工智能聊天框架。支持多种AI提供商&#xff08;OpenAI / Claude 3 / Gemini / Ollama / Qwen / De…

vue2+cesium初始化地图

目录 1、在vue2项目中下载cesium 2、安装loader 3、更改vue.config.js中的配置 4、main.js中引入 5、App.vue中设置样式 6、新建map.vue 其中代码如下&#xff1a; 7、在App.vue中使用Map组件 8、效果展示&#xff1a; 1、在vue2项目中下载cesium npm install cesium 可…

CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)

附件 calculate.html <!DOCTYPE html> <html lang"en"> <head><!-- 设置字符编码为 UTF-8&#xff0c;支持多语言字符集 --><meta charset"UTF-8"><!-- 设置响应式视图&#xff0c;确保页面在不同设备上自适应显示 --&…

TYUT设计模式精华版

七大原则 单一职责原则 职责要单一不能将太多的职责放在一个类中 开闭原则 软件实体对扩展是开放的&#xff0c;但对修改是关闭的 里氏代换原则 一个可以接受基类对象的地方必然可以接受子类 依赖倒转原则 要针对抽象层编程&#xff0c;而不要针对具体类编程 接口隔离原则 …

Android 使用OpenGLES + MediaPlayer 获取视频截图

概述 Android 获取视频缩略图的方法通常有: ContentResolver: 使用系统数据库MediaMetadataRetriever: 这个是android提供的类&#xff0c;用来获取本地和网络media相关文件的信息ThumbnailUtils: 是在android2.2&#xff08;api8&#xff09;之后新增的一个&#xff0c;该类为…

论文阅读——量子退火Experimental signature of programmable quantum annealing

摘要&#xff1a;量子退火是一种借助量子绝热演化解决复杂优化问题的通用策略。分析和数值证据均表明&#xff0c;在理想化的封闭系统条件下&#xff0c;量子退火可以胜过基于经典热化的算法&#xff08;例如模拟退火&#xff09;。当前设计的量子退火装置的退相干时间比绝热演…

Vue框架开发一个简单的购物车(Vue.js)

让我们利用所学知识来开发一个简单的购物车 &#xff08;记得暴露属性和方法&#xff01;&#xff01;&#xff01;&#xff09; 首先来看一下最基本的一个html框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…

瑞芯微方案主板Linux修改系统串口波特率教程,触觉智能RK3562开发板演示

遇到部分串口工具不支持1500000波特率&#xff0c;这时候就需要进行修改&#xff0c;本文以触觉智能RK3562开发板修改系统波特率为115200为例&#xff0c;介绍瑞芯微方案主板Linux修改系统串口波特率教程。 温馨提示&#xff1a;瑞芯微方案主板/开发板串口波特率只支持115200或…

攻防世界-fileclude-文件包含

赛前回顾 1.题目打开后是文件包含的代码&#xff0c;如下 函数作用 highlight_file(__FILE__) //显示代码到网页 isset //检查变量是否存在并且非null(空) !empty //php内置函数&#xff0c;检查变量是否为空或未设置&#xff0c;正常变量为空会触发&#xff0c;但是有个…

039集——渐变色之:CAD中画彩虹()(CAD—C#二次开发入门)

&#xff08;来左边儿 跟我一起画个龙&#xff0c;在你右边儿 画一道彩虹 ~~~~~~~~~~~ &#xff09; 效果如下&#xff1a; 以下展示部分颜色源码&#xff1a; namespace AcTools {public class Class1{public Wform.Timer timer;//定时器需建在类下面public s…

Spark和MapReduce场景应用和区别

文章目录 Spark和MapReduce场景应用和区别一、引言二、MapReduce和Spark的应用场景1. MapReduce的应用场景2. Spark的应用场景 三、MapReduce和Spark的区别1. 内存使用和性能2. 编程模型和易用性3. 实时计算支持 四、使用示例1. MapReduce代码示例2. Spark代码示例 五、总结 Sp…