美文网首页
Lab8 : 网络LED矩阵显示器 - 嵌入式与计算机网络

Lab8 : 网络LED矩阵显示器 - 嵌入式与计算机网络

作者: lmzqwer2 | 来源:发表于2016-06-04 02:58 被阅读455次

    前言

    本次实验延续上次实验的环境,使用MAX7219驱动8x8点阵。上位机使用Ubuntu 14.04,下位机使用Raspberry pi 2。

    使用的还是上次实验编译好的非阻塞式写入点阵支持内核模块。

    这次的实验跟计网实验好像啊好像啊。

    控制点阵显示字符

    通过write函数向device写入数据即可。

    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int Matrix;
    
    #define ALLCHAR "0123456789abcdefghijklmnopqrstuvwxyz"
    
    int main(){
        Matrix = open("/dev/matrix", O_WRONLY);
        if (Matrix < 0){
            fprintf(stderr, "Cound not open matrix device");
            exit(1);
        }
        write(Matrix, ALLCHAR, strlen(ALLCHAR));
        return 0;
    }
    
    

    编写网络程序接受TCP请求

    使用linux下的socket编程,接受外部TCP请求,并将其发送来的所有数据写入matrix设备即可实现显示功能。

    Socket流程图 | 图自[Linux的SOCKET编程详解](http://blog.csdn.net/hguisu/article/details/7445768)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    int Matrix;
    int server;
    
    #define PORT 8080
    #define ADDR "0.0.0.0"
    #define QUEUE 20
    
    #define BUFF_SIZE 2048
    
    int main(){
        // 打开matrix
        Matrix = open("/dev/matrix", O_WRONLY);
        if (Matrix < 0){
            fprintf(stderr, "Cound not open matrix device\n");
            exit(1);
        }
        // 建立服务器
        int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        struct sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_addr.s_addr = inet_addr(ADDR);
        serverAddr.sin_port = htons(PORT);
    
        // 绑定ip以及端口
        if (bind(server, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1){
            fprintf(stderr, "Count not bind %s:%d\n", ADDR, PORT);
            exit(1);
        }
    
        if (listen(server, QUEUE) == -1){
            fprintf(stderr, "Listen error\n");
            exit(1);
        }
    
        printf("Server running at %s:%d\n", ADDR, PORT);
    
        while (1){
            struct sockaddr_in clientAddr;
            socklen_t length = sizeof(clientAddr);
    
            // 对连入的连接进行处理
            int conn = accept(server, (struct sockaddr*)&clientAddr, &length);
            if (conn < 0){
                fprintf(stderr, "Connect error");
                exit(1);
            }
    
            printf("A new connection from %s:%d\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
    
            // 处理连接发送过来的字符
            while (1){
                char receiveBuf[BUFF_SIZE];
                int count;
                memset(receiveBuf, 0, sizeof(receiveBuf));
                
                // 接收字符
                count = recv(conn, receiveBuf, sizeof(receiveBuf), 0);
    
                // 如果接收到的字符为空,则表示离开
                if (count == 0){
                    close(conn);
                    break;
                }
                
                // 将接收到的所有字符发送给matrix进行显示
                write(Matrix, receiveBuf, count);
            }
        }
        close(server);
        return 0;
    }
    
    树莓派本地连入 上位机远程连入

    使用线程处理多个连接

    上一节的程序使用的是阻塞式的处理连接,这将导致服务器每次accept了一个连接之后,无法再处理其余连接。

    而这种情况的处理方式有很多。可以使用一个线程对应一个socket fd的方式进行阻塞式监听。也可以使用IO多路复用,如select、poll、epoll,在单线程的环境下进行高效的网络IO操作。

    使用线程的方式对于阻塞式程序的改动较小,基本上逻辑还是一致的。

    …………
    void* serverRecv(void* data){
        int conn = *(int*)data;
    
        while (1){
            char receiveBuf[BUFF_SIZE];
            int count;
            memset(receiveBuf, 0, sizeof(receiveBuf));
            
            count = recv(conn, receiveBuf, sizeof(receiveBuf), 0);
    
            if (count == 0){
                close(conn);
                break;
            }
            
            write(Matrix, receiveBuf, count);
        }
    
        pthread_exit(NULL);
        return NULL;
    }
    …………
    int main(){
    …………
        printf("Server running at %s:%d\n", ADDR, PORT);
    
        while (1){
            pthread_t thread;
            struct sockaddr_in clientAddr;
            socklen_t length = sizeof(clientAddr);
            int conn = accept(server, (struct sockaddr*)&clientAddr, &length);
            int result;
            if (conn < 0){
                fprintf(stderr, "Connect error");
                exit(1);
            }
    
            printf("A new connection from %s:%d\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
    
            result = pthread_create(&thread, NULL, serverRecv, &conn);
            if (result < 0){
                printf("Create thread error\n");
                exit(1);
            }
        }
    …………
    }
    

    在这个版本中,主程序只负责接受连接,而接受到的连接交由子线程进行监听处理。

    参考资料

    相关文章

      网友评论

          本文标题:Lab8 : 网络LED矩阵显示器 - 嵌入式与计算机网络

          本文链接:https://www.haomeiwen.com/subject/xvdldttx.html