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;
}