Yuu__ 2021-06-08 22:25 采纳率: 0%
浏览 16

Linux中C程序Tcp数据转串口输出,代码哪里出了问题?

只能发一次数据就结束了代码如下:

Windows客户端:

#include <stdio.h>

#include <Windows.h>

#define _CRT_SECURE_NO_WARNINGS

#pragma warning(disable:4996)

#pragma comment(lib,"ws2_32.lib")

#define  PORT 8888

#define  IP_ADDRESS "192.168.0.107"

 

int main(int argc, char* argv[])

{

WSADATA  Ws;

SOCKET ClientSocket;

struct sockaddr_in ClientAddr;

int Ret = 0;

char SendBuffer[MAX_PATH];

 

/* Init Windows Socket */

if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0)

{

printf("Init Windows Socket Failed::%d\n", GetLastError());

return -1;

}

 

/* Create Socket */

ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (ClientSocket == INVALID_SOCKET)

{

printf("Create Socket Failed::%d\n", GetLastError());

return -1;

}

 

ClientAddr.sin_family = AF_INET;

ClientAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);

ClientAddr.sin_port = htons(PORT);

memset(ClientAddr.sin_zero, 0x00, 8);

 

/* connect socket */

Ret = connect(ClientSocket, (struct sockaddr*)&ClientAddr, sizeof(ClientAddr));

if (Ret == SOCKET_ERROR)

{

printf("Connect Error::%d\n", GetLastError());

return -1;

}

else

{

printf("Connect succedded!\n");

}

 

while (1)

{

printf("Please send Informations:\n");

scanf("%s", SendBuffer);

 

/* send data to server */

Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);

if (Ret == SOCKET_ERROR)

{

printf("Send Info Error::%d\n", GetLastError());

break;

}

 

if (' ' == SendBuffer[0])

{

break;

}

}

 

/* close socket */

closesocket(ClientSocket);

WSACleanup();

 

return 0;

}

 

Linux服务端:

#include <netinet/in.h>    

#include <sys/types.h>    

#include <sys/socket.h>    

#include<sys/time.h>

#include <stdio.h>        

#include <stdlib.h>       

#include <string.h>       

#include <unistd.h>

#include <fcntl.h>

#include <termios.h>

#include<errno.h>

#include<assert.h>

#define DEV_NAME  "/dev/ttyUSB0"

 

#define HELLO_WORLD_SERVER_PORT    8888

#define LENGTH_OF_LISTEN_QUEUE 20

#define BUFFER_SIZE 1024

 

static int ret;

static int fd;

 

/*

 * 安全读写函数

 */

 

ssize_t safe_write(int fd, const void *vptr, size_t n)

{

size_t  nleft;

ssize_t nwritten;

const char *ptr;

 

ptr = vptr;

nleft = n;

 

while (nleft > 0)

{

if ((nwritten = write(fd, ptr, nleft)) <= 0)

{

if (nwritten < 0 && errno == EINTR)

nwritten = 0;

else

return -1;

}

nleft -= nwritten;

ptr += nwritten;

}

return(n);

}

 

ssize_t safe_read(int fd, void *vptr, size_t n)

{

size_t nleft;

ssize_t nread;

char *ptr;

 

ptr = vptr;

nleft = n;

 

while (nleft > 0)

{

if ((nread = read(fd, ptr, nleft)) < 0)

{

if (errno == EINTR)//被信号中断

nread = 0;

else

return -1;

}

else

if (nread == 0)

break;

nleft -= nread;

ptr += nread;

}

return (n - nleft);

}

 

int uart_open(int fd, const char *pathname)

{

assert(pathname);

 

/*打开串口*/

fd = open(pathname, O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)

{

perror("Open UART failed!");

return -1;

}

 

/*清除串口非阻塞标志*/

if (fcntl(fd, F_SETFL, 0) < 0)

{

fprintf(stderr, "fcntl failed!\n");

return -1;

}

 

return fd;

}

 

int uart_set(int fd, int baude, int c_flow, int bits, char parity, int stop)

{

struct termios options;

 

/*获取终端属性*/

if (tcgetattr(fd, &options) < 0)

{

perror("tcgetattr error");

return -1;

}

 

 

/*设置输入输出波特率,两者保持一致*/

switch (baude)

{

case 4800:

cfsetispeed(&options, B4800);

cfsetospeed(&options, B4800);

break;

case 9600:

cfsetispeed(&options, B9600);

cfsetospeed(&options, B9600);

break;

case 19200:

cfsetispeed(&options, B19200);

cfsetospeed(&options, B19200);

break;

case 38400:

cfsetispeed(&options, B38400);

cfsetospeed(&options, B38400);

break;

default:

fprintf(stderr, "Unkown baude!\n");

return -1;

}

 

/*设置控制模式*/

options.c_cflag |= CLOCAL;//保证程序不占用串口

options.c_cflag |= CREAD;//保证程序可以从串口中读取数据

 

/*设置数据流控制*/

switch (c_flow)

{

case 0://不进行流控制

options.c_cflag &= ~CRTSCTS;

break;

case 1://进行硬件流控制

options.c_cflag |= CRTSCTS;

break;

case 2://进行软件流控制

options.c_cflag |= IXON | IXOFF | IXANY;

break;

default:

fprintf(stderr, "Unkown c_flow!\n");

return -1;

}

 

/*设置数据位*/

switch (bits)

{

case 5:

options.c_cflag &= ~CSIZE;//屏蔽其它标志位

options.c_cflag |= CS5;

break;

case 6:

options.c_cflag &= ~CSIZE;//屏蔽其它标志位

options.c_cflag |= CS6;

break;

case 7:

options.c_cflag &= ~CSIZE;//屏蔽其它标志位

options.c_cflag |= CS7;

break;

case 8:

options.c_cflag &= ~CSIZE;//屏蔽其它标志位

options.c_cflag |= CS8;

break;

default:

fprintf(stderr, "Unkown bits!\n");

return -1;

}

 

/*设置校验位*/

switch (parity)

{

/*无奇偶校验位*/

case 'n':

case 'N':

options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验

options.c_cflag &= ~INPCK;//INPCK:使奇偶校验起作用

break;

/*设为空格,即停止位为2位*/

case 's':

case 'S':

options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验

options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位

break;

/*设置奇校验*/

case 'o':

case 'O':

options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验

options.c_cflag |= PARODD;//PARODD:若设置则为奇校验,否则为偶校验

options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用

options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位

break;

/*设置偶校验*/

case 'e':

case 'E':

options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验

options.c_cflag &= ~PARODD;//PARODD:若设置则为奇校验,否则为偶校验

options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用

options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位

break;

default:

fprintf(stderr, "Unkown parity!\n");

return -1;

}

 

/*设置停止位*/

switch (stop)

{

case 1:

options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位

break;

case 2:

options.c_cflag |= CSTOPB;//CSTOPB:使用两位停止位

break;

default:

fprintf(stderr, "Unkown stop!\n");

return -1;

}

 

/*设置输出模式为原始输出*/

options.c_oflag &= ~OPOST;//OPOST:若设置则按定义的输出处理,否则所有c_oflag失效

 

/*设置本地模式为原始模式*/

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

/*

 *ICANON:允许规范模式进行输入处理

 *ECHO:允许输入字符的本地回显

 *ECHOE:在接收EPASE时执行Backspace,Space,Backspace组合

 *ISIG:允许信号

 */

 

 /*设置等待时间和最小接受字符*/

options.c_cc[VTIME] = 0;//可以在select中设置

options.c_cc[VMIN] = 1;//最少读取一个字符

 

/*如果发生数据溢出,只接受数据,但是不进行读操作*/

tcflush(fd, TCIFLUSH);

 

/*激活配置*/

if (tcsetattr(fd, TCSANOW, &options) < 0)

{

perror("tcsetattr failed");

return -1;

}

 

return 0;

}

 

int uart_read(int fd, char *buffer, size_t len)

{

ssize_t cnt = 0;

fd_set rfds;

struct timeval time;

 

/*将文件描述符加入读描述符集合*/

FD_ZERO(&rfds);

FD_SET(fd, &rfds);

 

/*设置超时为15s*/

time.tv_sec = 15;

time.tv_usec = 0;

 

/*实现串口的多路I/O*/

ret = select(fd + 1, &rfds, NULL, NULL, &time);

switch (ret)

{

case -1:

fprintf(stderr, "select error!\n");

return -1;

case 0:

fprintf(stderr, "time over!\n");

return -1;

default:

cnt = safe_read(fd, buffer, len);

if (cnt == -1)

{

fprintf(stderr, "read error!\n");

return -1;

}

return cnt;

}

}

 

int uart_write(int fd, char *buffer, size_t len)

{

ssize_t cnt = 0;

 

cnt = safe_write(fd, buffer, len);

if (cnt == -1)

{

fprintf(stderr, "write error!\n");

return -1;

}

 

return cnt;

}

 

int uart_close(int fd)

{

assert(fd);

close(fd);

 

/*可以在这里做些清理工作*/

 

return 0;

}

 

 

 

int main(int argc, char **argv)

{

    struct sockaddr_in server_addr;

int server_socket;

int opt = 1;

   

    bzero(&server_addr,sizeof(server_addr)); 

 

    server_addr.sin_family = AF_INET;

    server_addr.sin_addr.s_addr = htons(INADDR_ANY);

    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);

 

/* create a socket */

    server_socket = socket(PF_INET,SOCK_STREAM,0);

    if( server_socket < 0)

    {

        printf("Create Socket Failed!");

        exit(1);

    }

 

    /* bind socket to a specified address*/

    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))

    {

        printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); 

        exit(1);

    }

 

    /* listen a socket */

    if(listen(server_socket, LENGTH_OF_LISTEN_QUEUE))

    {

        printf("Server Listen Failed!"); 

        exit(1);

    }

 

 

/* uart */

    char *buffer = "something to write";

size_t w_len = sizeof(buffer);

 

char buffer[BUFFER_SIZE];

 

fd = uart_open(fd, "/dev/ttyUSB0");/*串口号/dev/ttySn,USB口号/dev/ttyUSBn*/

if (fd == -1)

{

fprintf(stderr, "uart_open error\n");

exit(EXIT_FAILURE);

}

 

if (uart_set(fd, 9600, 0, 8, 'N', 1) == -1)

{

fprintf(stderr, "uart set failed!\n");

exit(EXIT_FAILURE);

}

 

ret = uart_write(fd, w_buf, w_len);

if (ret == -1)

{

fprintf(stderr, "uart write failed!\n");

exit(EXIT_FAILURE);

}

 

 

 

/* run server */

    while (1) 

    {

        struct sockaddr_in client_addr;

int client_socket;

        socklen_t length;

char buffer[BUFFER_SIZE];

 

/* accept socket from client */

length = sizeof(client_addr);

        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);

        printf("Listening...\n");

        if( client_socket < 0)

        {

            printf("Server Accept Failed!\n");

            break;

        }

        

/* receive data from client */

while(1)

{

bzero(buffer, BUFFER_SIZE);

length = recv(client_socket, buffer, BUFFER_SIZE, 0);

if (length < 0)

{

printf("Server Recieve Data Failed!\n");

break;

}

 

if(' ' == buffer[0])

{

printf("Quit from client!\n");

break;

ret = uart_close(fd);

if (ret == -1) {

{

fprintf(stderr, "uart_close error\n");

exit(EXIT_FAILURE);

}

 

exit(EXIT_SUCCESS);

}

printf("The information received from the client is as follows:\n");

printf("%s\n", buffer);

 

 

/*UART*/

ret = uart_open(fd, pathname);

printf("USB0 open!\n");

 

ret = uart_write(fd, buffer, 1024);

if (ret == -1)

{

fprintf(stderr, "uart write failed!\n");

exit(EXIT_FAILURE);

}

 

}

 

            close(client_socket);

    }

 

 

 

 

    close(server_socket);

    return 0;

}

  • 写回答

1条回答 默认 最新

  • 有问必答小助手 2021-06-09 19:28
    关注

    你好,我是有问必答小助手。为了技术专家团更好地为您解答问题,烦请您补充下(1)问题背景详情,(2)您想解决的具体问题,(3)问题相关代码图片或者报错信息。便于技术专家团更好地理解问题,并给出解决方案。

    您可以点击问题下方的【编辑】,进行补充修改问题。

    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器