WSL和Windows建立TCP通信协议

news2024/11/15 8:38:31

1.windows配置

首先是windows端,启动TCP服务端,用来监听指定的端口号,其中IP地址可以设置为任意,否则服务器可能无法正常打开。

addrSer.sin_addr.S_un.S_addr = INADDR_ANY;

recv函数用来接收客户端传输的数据,其中sum表示接收到的字节数。

为了能将接收到的char数据转换成16进制形式,方便与发送数据进行比对。

rece = ToHexString((unsigned char*)recvbuf, sum);

这里sum不能替换为strlen(recvbuf),strlen在检测到"00"后会自动结束,打印的数据不全。

string ToHexString(unsigned char* input, int datasize)
{
        stringstream ss;
        ss << setbase(16) << setfill('0');
        for (int i = 0; i < datasize; i++)
                ss << setw(2) << (UINT)input[i];
        return ss.str();
}

TCP接收到的不是一个一个的数据,而是一段一段的数据,中间可能包含着多条信息,需要根据起始位将信息提取出来。

vector<int> positions = findAllSubstringPositions(rece, "aaa55a");
vector<string> s;
if(positions.size()>0){
        s.push_back(rece.substr(0, positions[0] + 2));
        for (int i = 1; i < positions.size(); i++) {
                cout << positions[i - 1] << endl;
                s.push_back(rece.substr(positions[i-1] + 2, positions[i]- positions[i - 1]));
        }
        s.push_back(rece.substr(positions[positions.size()-1]+2));
}
else {
        s.push_back(rece);
}
for(int j=0;j<= positions.size();j++)
        cout << s[j] << endl;

这里由于不知道一段包含命令的个数,所以用vector容器来存放比较合适,同时substr第一个参数是起始位置,第二个参数是需要提取字符串的长度,不是终止位置。

2.WSL配置

WSL作客户端,用来监听串口数据并返还给服务端。

第一步:让WSL可以检测到USB

powershell输入usbipd list查看当前USB设备(电脑间测试需要串口盒辅助,另外一台电脑打开串口调试助手,向WSL发送十六进制数据)

usbipd bind --busid 1-6   共享串口

usbipd attach --wsl -b 1-6   附加USB设备到WSL上

WSL输入lsusb检测当前USB设备

ls /dev/tty*查看USB设备的端口号

第二步:WSL开启串口监听

根据查询到的端口号配置端口

    //listen uart
    fd1 = open( "/dev/ttyS9", O_RDWR);
    if (fd1 == -1) {
        printf("open error!\n");
    }
    int nset = set_opt(fd1, 115200, 8, 'N', 1);
    if (nset == -1) {
        printf("set error!\n");
    }

第三步:配置接收线程

主函数开启线程std::thread uart(uart_read);

while(1)循环里连续接收n = read(fd1, send_buf, UART_BUFF);

n表示接收到的字符串长度,这里read可能会分段接收,加入起始位和长度的判断

        if(n>0){
            if(n>2){
                if(ToHexString((unsigned char*)send_buf,2) == "a55a"){
                    flag=1;
                    count=0;
                    memset(rece_buf,'\0',UART_BUFF);
                    numchar = (unsigned char)send_buf[2];
                    sum = (int)numchar;
                }
            }
            if(flag){
                for(int i=count;i<(count+n);i++){
                    rece_buf[i] = send_buf[i-count];
                }
                count += n;
                if(sum == (count-2)){
                    cout << ToHexString((unsigned char*)rece_buf,sum+2) << endl;
                    len=send(client_sockfd, rece_buf, count, 0);//TCP客户端发送
                    count = 0;
                }else if(sum < (count-2)){
                    flag = 0;
                    count = 0;
                }
            }
        }

这里数据的长度为unsigned char类型,用int强转

count表示接收到的字符串长度,其中rece_buf不能使用strcat来进行拼接,还是"00"的问题。

第四步:文件编译

一般的文件编译使用gcc -o 工程名 工程文件的格式

而std::thread则要

g++ -o 工程名 工程文件名 -lpthread -std=c++11

执行:

        ./工程名

完整代码

#include<iostream>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <thread>
#include <time.h>
#include <exception>
#include <syslog.h>
#include <stdlib.h>
#include <sstream>
#include <iomanip>
#include <string>

using namespace std;
typedef unsigned int UINT;
#define UART_BUFF 2048

int client_sockfd;
int len;
int fd1=-1;

string ToHexString(unsigned char* input, int datasize)
{
	stringstream ss;
	ss << setbase(16) << setfill('0');
	for (int i = 0; i < datasize; i++)
		ss << setw(2) << (UINT)input[i];
	return ss.str();
}

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;

    if  ( tcgetattr( fd,&oldtio)  !=  0)
    {
        perror("SetupSerial 1");
        return -1;
    }

    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag  |=  CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch( nBits )
    {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }

    switch( nEvent )
    {
        case 'O':
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'E':
            newtio.c_iflag |= (INPCK | ISTRIP);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            break;
        case 'N':
            newtio.c_cflag &= ~PARENB;
            break;
    }

    switch( nSpeed )
    {
        case 2400:
            cfsetispeed(&newtio, B2400);
            cfsetospeed(&newtio, B2400);
            break;
        case 4800:
            cfsetispeed(&newtio, B4800);
            cfsetospeed(&newtio, B4800);
            break;
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
        case 460800:
            cfsetispeed(&newtio, B460800);
            cfsetospeed(&newtio, B460800);
            break;
        default:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
    }

    if( nStop == 1 )
        newtio.c_cflag &=  ~CSTOPB; 
    else if ( nStop == 2 )
        newtio.c_cflag |=  CSTOPB;

    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH);

    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }

    return 0;
}

void uart_read(){
	char send_buf[UART_BUFF];
	int flag=0;
	int sum=0,count=0;
	char rece_buf[UART_BUFF];
    char send_buf_use[UART_BUFF];
	string numStr;
    unsigned char numchar;
    int n;
	while(1){
        n = read(fd1, send_buf, UART_BUFF);
        //cout << n << endl;
		if(n>0){
			if(n>2){
				if(ToHexString((unsigned char*)send_buf,2) == "a55a"){
					flag=1;
					count=0;
					memset(rece_buf,'\0',UART_BUFF);
                    numchar = (unsigned char)send_buf[2];
                    sum = (int)numchar;
                    // cout << ToHexString((unsigned char*)send_buf,n) << "***" << endl;
				}
			}
			if(flag){
				cout << ToHexString((unsigned char*)send_buf,n) << "***" << endl;
				for(int i=count;i<(count+n);i++){
					rece_buf[i] = send_buf[i-count];
				}
				count += n;
				//cout << ToHexString((unsigned char*)rece_buf,count) << endl;
			
				if(sum == (count-2)){
                    cout << ToHexString((unsigned char*)rece_buf,sum+2) << endl;
					len=send(client_sockfd, rece_buf, count, 0);
					count = 0;
				}else if(sum < (count-2)){
					flag = 0;
					count = 0;
				}
			}
		}
        //else
            //usleep(5000);
	}
	return;	
}

int main()
{
	struct sockaddr_in remote_addr;
   	char recv_buf[UART_BUFF];
   	char send_buf[UART_BUFF];
	memset(&remote_addr, 0, sizeof(remote_addr));
	remote_addr.sin_family=AF_INET;
	remote_addr.sin_addr.s_addr=inet_addr("192.168.192.100");
	remote_addr.sin_port=htons(6666);
	
	//listen uart
	fd1 = open( "/dev/ttyS9", O_RDWR);
	if (fd1 == -1) {
	    printf("open error!\n");
	}
	int nset = set_opt(fd1, 115200, 8, 'N', 1);
	if (nset == -1) {
	    printf("set error!\n");
	}
	
	//IPv4 tcp
	if((client_sockfd=socket(PF_INET, SOCK_STREAM, 0))<0)
	{
		cout<<"socket error";
		return 1;
	}
	
	if(connect(client_sockfd, (struct sockaddr*)&remote_addr, sizeof(struct sockaddr))<0)
	{
		cout<<"connect error";
		return 1;
	} 
	
	cout<<"connected to server"<<endl;
	std::thread uart(uart_read);
	
	while(1)
	{
		usleep(100);
	}
	uart.join();
	close(client_sockfd);
	close(fd1);
	return 0;
}
 
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏加速器哪个好用

对于游戏加速器&#xff0c;确实有很多不同的选择&#xff0c;每个加速器都有其独特的特点和优势。不过&#xff0c;我可以给你推荐一个最新上线的较受欢迎且评价较高的游戏加速器&#xff0c;供你参考&#xff1a; 深度加速器&#xff1a; 广泛支持&#xff1a;支持国内外众多…

RocketMQ批量消息

RocketMQ消息发送基本示例(推送消费者)-CSDN博客 RocketMQ消费者主动拉取消息示例-CSDN博客 RocketMQ顺序消息-CSDN博客 RocketMQ广播消息-CSDN博客 RocketMQ延时消息-CSDN博客 批量消息 批量消息是指将多条消息合并成一个批量消息,一次发送出去,原先的都是一次发一条.批量…

springboot四川旅游攻略分享互动平台-计算机毕业设计源码70222

摘 要 本研究基于Spring Boot框架开发了一款高效、可靠的四川旅游攻略分享互动平台。该系统主要面向管理员、普通用户和商家用户&#xff0c;涵盖了多个功能模块&#xff0c;包括旅游景点、旅游攻略、景点订单、酒店订单、酒店信息等。通过对系统需求的分析和设计&#xff0c;…

从数据规划到产品运营,拆解数据资产产品化的6大路径

数据资源入表对于企业数据资产的估值影响并不大&#xff0c;要想提升数据资产的整体价值&#xff0c;将数据资产进行产品化是更有效的途径之一。 那么&#xff0c;数据资产产品化的具体路径是怎样的&#xff1f; 在由WakeData惟客数据联合星光数智推出的直播栏目《星光对话》…

打破自闭症束缚:儿童康复案例揭秘

在自闭症的阴霾下&#xff0c;孩子们仿佛被困在一个无形的牢笼中&#xff0c;与外界的世界隔绝。然而&#xff0c;通过不懈的努力和科学的康复方法&#xff0c;许多孩子正在逐渐打破这一束缚&#xff0c;走向充满希望的未来。让我们一同走进几个令人鼓舞的儿童康复案例&#xf…

如何通过阿里云服务器部署hexo博客(超详细)

&#x1f44f;大家好&#xff01;我是和风coding&#xff0c;希望我的文章能给你带来帮助&#xff01; &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;点击 我的主页 还可以看到和风的其他内容噢&#x…

零基础入门转录组数据分析——机器学习算法之boruta(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09;1. boruta基础知识2. boruta&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理…

[Docker][Docker Volume]详细讲解

目录 1.什么是存储卷&#xff1f;2.为什么需要存储卷&#xff1f;1.数据丢失问题2.性能问题3.宿主机和容器互访不方便4.容器和容器共享不方便 3.存储卷分类1.volume docker 管理卷2.bind mount 绑定数据卷3.tmpfs mount 临时数据卷 5.管理卷 Volume1.创建卷1.-v 参数2.--mount …

《Milvus Cloud向量数据库指南》——向量数据库性价比大比拼:谁才是性能之王?

在分析这份向量数据库(Vector Databases)的性价比排名表格时,我们需要从多个维度深入探讨,包括但不限于硬件配置、价格/性能比(QP$,即每百万次查询所花费的价格)、数据集大小、查询类型(无标量过滤、低标量过滤、高标量过滤)以及不同服务提供商之间的比较。以下是一个…

微波治疗仪,美容仪,爆脂仪电源板

分享一下爆脂仪&#xff0c;美容仪&#xff0c;微波治疗仪电源板&#xff0c;高压输出为-2000v&#xff0c;驱动电流最大100mA&#xff0c;匹配磁控管功率输出100w

KubeBlocks v0.9 解读|最高可管理 10K 实例的 InstanceSet 是什么?

实例&#xff08;Instance&#xff09;是 KubeBlocks 中的基本单元&#xff0c;它由一个 Pod 和若干其它辅助对象组成。为了容易理解&#xff0c;你可以先把它简化为一个 Pod&#xff0c;下文中将统一使用实例这个名字。 InstanceSet 是一个通用 Workload API&#xff0c;负责…

python-进度条和计时器

from tqdm import tqdm import time# 设置任务的总步骤数 total_steps 100# 使用tqdm创建进度条 with tqdm(totaltotal_steps, unitstep) as pbar:# 开始计时start_time time.time()# 模拟任务步骤for i in range(total_steps):# 模拟每一步的工作负载time.sleep(0.1) # 假设…

C语言:自定义类型进阶(结构体、联合体、枚举)

自定义类型&#xff08;结构体、联合体、枚举&#xff09; 一、结构体&#xff08;一&#xff09;结构体的内存对齐1、结构体内存对齐规则&#xff08;1&#xff09;引子&#xff08;2&#xff09;offsetof 宏函数&#xff08;3&#xff09;内存对齐原理&#xff08;4&#xff…

【HM】DevEco Studio提供Hot Reload(热重载)能力确实好用!帮助开发者更快速进行调试。但要注意以下几点?

​​ 仅支持开发者在真机上运行/调试运行&#xff1a; 1、运行时&#xff0c;选择带H标识的entry&#xff1b; 2、运行设备选择已连接的真机&#xff1b; 3、运行中修改了文件后&#xff0c;点击H标识&#xff0c;在真机即刻可见效果。 注意约束条件&#xff1a; 只支持真…

硬盘信息,电脑硬盘查看工具

硬盘信息&#xff0c;电脑硬盘查看工具 硬盘信息&#xff0c;电脑硬盘查看工具

FPGA开发——状态机的使用

一、概述 我们在使用FPGA进行开发的过程当中&#xff0c;实现一个东西用得最多的实现方法就是状态机的实现方法&#xff0c;用一句话总结就是万物皆可状态机&#xff0c;这和我们在学习Linux时常说的在Linux中万物都是文件差不多&#xff0c;这里就主要就是突出状态机的应用范…

Moretl 文件同步工具 1.1.0.3

永久免费: 前往Gitee最新版本 更新内容 Winform全部切换到.Net Framework 4.0. 更符合大部分的自动化设备. Web提供.Net Framework 4.0的运行时环境安装包 Web打开时,若当前IP为设备,直接显示设备信息 介绍 用途: 定时全量或增量 采集工控机,办公电脑文件以及日志.(SCADA,I…

Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件

​​ jmeter性能测试 1. Jmeter简介 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件。相比Loadrunner而言&#xff0c;JMeter小巧轻便且免费&#xff0c;逐渐成为了主流的性能测试工具&#xff0c;是每个测试人员都必须要掌握的工具之一。 本文为JMeter…

进口不锈钢309S螺栓的应用优势

进口不锈钢309S螺栓因其优异的性能和广泛的应用范围而在许多行业中备受青睐。309S不锈钢是一种含硫的易切削不锈钢&#xff0c;具有良好的耐高温和耐腐蚀性能&#xff0c;使其成为高温环境下理想的选择。下面我们就来详细探讨一下进口不锈钢309S螺栓的应用优势。 一、309S不锈钢…

请你谈谈:spring拦截器的应用-preHandle postHandle afterCompletion执行顺序问题的讨论?

首先我们&#xff0c;给出一个demo来看下拦截器方法执行顺序&#xff1a; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.…