如何使用socat pty通过两个C程序发送和接收数据?

问题描述 投票:0回答:1

我正在尝试使用伪 tty 发送和接收数据,以便稍后使用链接到串行 RS232 USB 适配器的真实 tty。

我首先使用

socat
创建伪 tty:

sudo socat -d -d pty,link=./ttyUSB0,echo=0,perm=0666 pty,link=./ttyUSB1,echo=0,perm=0666

发送方似乎成功发送了数据,但接收方没有收到数据。我首先运行在第一次调用

read()
函数时阻塞的接收器。然后我运行发射器向其发送数据。

这是发射器程序:

#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include <termios.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

float data[100000];

int main() {
  int fdm = -1;
  fdm = open("./ttyUSB0",O_RDWR);
  if(fdm < 0) { perror("Error"); exit(EXIT_FAILURE); }
  grantpt(fdm);
  unlockpt(fdm);
  
  int i;
  for(i=0; i<100000; i++) {
    if(i%100 == 0) { printf("\rTransmit %d / %d",i,100000); fflush(stdout); }
    write(fdm,&data[i],sizeof(float));
  }
}

接收程序:

#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include <termios.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

float data[100000];

int main() {
  int fds = open("./ttyUSB1",O_RDWR);
  if(fds < 0) { perror("Error"); exit(EXIT_FAILURE); }
  grantpt(fds);
  unlockpt(fds);
  
  int i;
  for(i=0; i<100000; i++) {
    if(i%100 == 0) { printf("\rReceive %d / %d",i,100000); fflush(stdout); }
    read(fds,&data[i],sizeof(float));
  }
}

当我运行

cat ./ttyUSB1
echo abcd >> ./ttyUSB0
时,
cat
命令打印使用
echo
发送的消息。

所以问题似乎出在我的程序上。

c linux tty pty
1个回答
0
投票

我按照mbedded ninja关于串口编程的教程,像真正的tty一样配置伪tty。现在看来工作没有问题。

这是发射器的代码,对接收器进行了相同的 tty 设置:

#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include <termios.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

float data[100000];

int main() {
  int fdm = -1;
  fdm = open("./ttyUSB0",O_RDWR);
  if(fdm < 0) { perror("Error"); exit(EXIT_FAILURE); }
  grantpt(fdm);
  unlockpt(fdm);
  
  struct termios tty;
  if(tcgetattr(fdm, &tty) != 0) {
      printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
  }
  tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
  tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
  
  tty.c_cflag &= ~CSIZE; // Clear all the size bits, then use one of the statements below
  tty.c_cflag |= CS8; // 8 bits per byte (most common)
  
  tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
  tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
  tty.c_lflag &= ~ICANON; // disable input cannonical mode
  tty.c_lflag &= ~ECHO; // Disable echo
  tty.c_lflag &= ~ECHOE; // Disable erasure
  tty.c_lflag &= ~ECHONL; // Disable new-line echo
  
  tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
  
  tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
  tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
  
  tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
  tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
  
  tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
  tty.c_cc[VMIN] = 0;
  
  cfsetispeed(&tty, B115200);
  cfsetospeed(&tty, B115200);
  cfsetspeed(&tty, B115200); // set both input and output speed
  
  if (tcsetattr(fdm, TCSANOW, &tty) != 0) {
    printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
  }
  
  int i;
  for(i=0; i<100000; i++) {
    if(i%100 == 0) { printf("\rTransmit %d / %d",i,100000); fflush(stdout); }
    write(fdm,&data[i],sizeof(float));
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.