zoukankan      html  css  js  c++  java
  • tcp与串口透传(select)

    介绍

    tcp作为服务端,监听端口8888,实现串口透传,这里是使用select监听tcp的receive和串口的read,单工通信

    • -p 指定tcp端口
    • -s 指定串口
    • -b 指定波特率 支持4800 9600 115200
    • -? 打印具体用法

    程序

    #include <sys/types.h>         
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <linux/serial.h>
    #include <sys/ioctl.h>
    #include <sys/select.h>
    #include <unistd.h>
    
    
    #include <termios.h>
    
    void Test_err(int flg)
    {
        if(flg<0)
        {
            perror(strerror(errno));
            exit(1);
        }
    }
    
    int main(int argc, char** argv)
    {
        printf("usage : %s ?
    ",argv[0]);
        
    
    
        short listenPort=8888; 
        unsigned char uart_port[100]={"/dev/ttyS2"};
        int bps=0;
        unsigned int   baudRate= B9600;
    
        int  opt;
        while ((opt=getopt(argc,argv,"p:s:b:?")) != -1)
        {
            switch (opt)
            {
            case 'p':
                listenPort = atoi(optarg);
                break;
            case 's':
                memset(uart_port,0,sizeof(uart_port));
                strncpy(uart_port,optarg,99);
                break;
            case 'b':
                bps = atoi(optarg);
                break;
            default: /* '?' */
                       fprintf(stderr, "Usage: %s [-p port -s serial port  -b baund]  
    ",
                               argv[0]);
                       exit(EXIT_FAILURE);
            }
        }
    
        switch(bps)
        {
        case 4800:
            baudRate=B4800;
            break;
        case 19200:
            baudRate=B19200;
            break;
        case 38400:
            baudRate=B38400;
            break;
        case 57600:
            baudRate=B57600;
            break;
        case 115200:
            baudRate=B115200;
            break;
        default:
            baudRate=B9600;
            bps=9600;
            break;
        }
    
    
    
    
        printf("tcp-server...enter
    ");
        printf("set uartport is %d
    ",bps);
        printf("set uartspeed is %s
    ",uart_port);
        printf("set tcpport is %d
    ",listenPort);
    
        
    
    
    // uart--------------------------------------------------------
        int uart_fd=open(uart_port, O_RDWR | O_NOCTTY | O_NDELAY);
    
        struct termios newtio;
        memset(&newtio,0, sizeof( newtio ));
        newtio.c_cflag=0;
        newtio.c_iflag=0;
        newtio.c_cflag  |=  CLOCAL | CREAD; 
        newtio.c_cflag &= ~CSIZE; 
        newtio.c_cflag |= CS8;
        newtio.c_cflag &= ~PARENB;
        newtio.c_cflag &=  ~CSTOPB; 
        newtio.c_cc[VTIME] = 0;
        newtio.c_cc[VMIN]  = 0;
        cfsetispeed(&newtio, baudRate);
        cfsetispeed(&newtio, baudRate);
        tcflush(uart_fd,TCIFLUSH);
    
        if((tcsetattr(uart_fd,TCSANOW,&newtio))!=0)
        {
            perror("uart open error
    ");
            return -1;
        }
    
        int portfd;
        #if (__GNUC__ == 4 && __GNUC_MINOR__ == 3)
    	struct my_serial_rs485 rs485conf;
    	struct my_serial_rs485 rs485conf_bak;
        #else
        	struct serial_rs485 rs485conf;
        	struct serial_rs485 rs485conf_bak;
        #endif
        
    
        portfd=uart_fd;
        /* Driver-specific ioctls: ...linux-3.10.xincludeuapiasm-genericioctls.h */
        #define TIOCGRS485      0x542E
        #define TIOCSRS485      0x542F
        if (ioctl (portfd, TIOCGRS485, &rs485conf) < 0) 
    	{
    		/* Error handling.*/ 
    		// Log::Inf("ioctl TIOCGRS485 error.
    ");
            printf( "[ERR] ioctl TIOCGRS485 error.
    ");
    	}
    	/* Enable RS485 mode: */
    	rs485conf.flags |= SER_RS485_ENABLED;
    
    	/* Set logical level for RTS pin equal to 1 when sending: */
    	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
    	//rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
    
    	/* set logical level for RTS pin equal to 0 after sending: */ 
    	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
    	//rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
    
    	/* Set rts delay after send, if needed: */
    	rs485conf.delay_rts_after_send = 0x80;
    
    	if (ioctl (portfd, TIOCSRS485, &rs485conf) < 0)
    	{
    		/* Error handling.*/ 
    		printf("ioctl TIOCSRS485 error.
    ");
            
    	}
    
    	if (ioctl (portfd, TIOCGRS485, &rs485conf_bak) < 0)
    	{
    		/* Error handling.*/ 
    		printf("ioctl TIOCGRS485 error.
    ");
        }
        /*----------------------------------------------------*/
        unsigned char test_msg[]="this is send by uart
    ";
        int uart_sent_cnt = write(uart_fd, test_msg, sizeof(test_msg));
    
    
    
    // tcp--------------------------------------------------------
    
    
        int listen_fd=-1;
        int accept_fd=-1;
        int flags;
        int max_listen_num=10;
        unsigned char r_buf[255];
        int n;
    
        struct sockaddr_in server_addr;
        struct sockaddr_in  clinet_addr;
    
    
        
    
    
        listen_fd=socket(AF_INET, SOCK_STREAM, 0);
        Test_err(listen_fd);
    
        memset(&server_addr,0,sizeof(server_addr));
        server_addr.sin_family      = AF_INET;
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        server_addr.sin_port        = htons(listenPort);
    
        int i = 1;/* 允许重复使用本地地址与套接字进行绑定 */
        setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
    
        flags=bind(listen_fd, (struct sockaddr *)&server_addr,sizeof(struct sockaddr));
        Test_err(flags);
    
        flags= listen(listen_fd, max_listen_num);
        Test_err(flags);
    
        int clinet_addr_len=sizeof(clinet_addr);
    __ACCEPT_AGAIN__:    
        accept_fd= accept(listen_fd, (struct sockaddr *)&clinet_addr, &clinet_addr_len);
        // show clinet message
        printf("accept_fd is %d 
    ",accept_fd);
        printf("port=%d
    ",ntohs(clinet_addr.sin_port));
        unsigned char strbuf[20];
        inet_ntop(AF_INET,&clinet_addr.sin_addr,strbuf,sizeof(strbuf));
        printf("ip=%s
    ",strbuf);
        memset(r_buf , 0, sizeof(r_buf));
     
    
    
        int maxfd; 
        fd_set rset, allset;
        struct timeval tv;
        FD_ZERO(&allset);
        FD_SET(uart_fd, &allset);
        FD_SET(accept_fd, &allset);
        memset(&tv, 0, sizeof(tv));
        tv.tv_usec = 1000 * 1000;
    
    
        int len=0;
        while (accept_fd)
        {
            rset=allset;
            maxfd=(accept_fd>uart_fd?accept_fd:uart_fd);
     
            flags=select(maxfd + 1, &rset, NULL, NULL, &tv);
            Test_err(flags);
    
            // get from tcp>>>>>uart
            if (FD_ISSET(accept_fd, &rset))
            {
                n = recv(accept_fd, r_buf, 100, 0);
                Test_err(n);
                if(n)
                {
                    //write(0,r_buf,n);
                    printf("Get from tcp %d
    ",n);
                    write(uart_fd,r_buf,n);
                }
                else
                {
                    printf("socket is disconnect
    ");
                    goto __ACCEPT_AGAIN__;
                }
            }
            // get from uart>>>>tcp
            else if (FD_ISSET(uart_fd, &rset))
            {
                usleep(100000);//100ms  这里等待接受多一点的数据
                int ret = read(uart_fd, (char*)r_buf,sizeof(r_buf));
                if (ret < 0)
                {
                    if ((errno == EAGAIN) ||
                        (errno == EWOULDBLOCK) ||
                        (errno == EINTR))
                    {
                        printf("Serial,read timeout error:%s. ignore ti!!!", strerror(errno));
                        ret = 0;
                    }
                }
                else
                {
                    printf("Get from uart %d
    ",ret);
                    send(accept_fd, r_buf, ret, 0);
                }
            }
        }
        printf("tcp-server...exit
    ");
        return 0;
    }
    
  • 相关阅读:
    firewall详解
    Fiddler使用
    Asp.net Core过滤器
    单例模式
    C# 收银机顾显(客显)及打印小票(58热敏打印机)
    sqlite批量处理数据性能优化
    sqlite 插入数据 too many variables
    winform textbox控件keydown、keypress、keyup简单介绍
    ie兼容placeholder效果
    asp.net mvc全局异常捕获
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/11660019.html
Copyright © 2011-2022 走看看