Assignment 108: Lab 8:网络LED矩阵显示器

这个实验的目的是掌握Linux网络程序和多线程程序的编写,实现一个网络访问的LED矩阵显 示器。

实验目的

  1. 复习socket编程(网络原理课);
  2. 实现一个网络访问的LED矩阵显示器。

实验器材

硬件

以下为自备(可选)器材:

软件

实验步骤

1.      设计外部设备方案,画连线示意图;

2.      在面包板上连线,完成外部电路;

这次实验的连线图和上次一致:

无标题

具体连线拍照效果可见后文的结果展示。

3.      编写Linux应用程序,能通过第七次实验的设备驱动程序控制LED矩阵显示字符串,每个字符停留500ms

启动led显示屏的方法和上次一致,只是上次在终端直接使用echo输出,这次试用write函数。运行之前需要安装内核模块。并且使用root模式。

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int main(){

int matrix;

char str[10]=”123456”;

    matrix = open("/dev/matrix", O_WRONLY);

    if (matrix < 0){   //open failed

         return(-1);

    }

    write(Matrix, str, strlen(str));

    return 0;

}

 

4.      编写Linux应用程序,能通过TCP接受一个连接,将发来的文字在LED矩阵上流动显示出来;

编写socket程序,和之前计算机网络课程做的实验类似。由于需要支持多个终端同时登陆,这里需要使用多线程,来防止一个终端连接后recv命令的阻塞。函数中首先开始监听是否有客户端连接,一旦有客户端连入,就新开启一个线程用于监听输入。代码如下:

#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

 

void* onServerRecv(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;

        }

        printf("Receiver: %s",receiveBuf);

        write(Matrix, receiveBuf, count);

    }

    pthread_exit(NULL);

    return NULL;

}

 

int main(){

 

    // open matrix

    Matrix = open("/dev/matrix", O_WRONLY);

    if (Matrix < 0){

        printf("Open matrix failed.\n");

        exit(1);

    }

    // start server

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

    // bind

    if (bind(server, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1){

        printf("Bind failed %s:%d\n", ADDR, PORT);

        exit(1);

   if (listen(server, QUEUE) == -1){

        printf("Listen failed.\n");

        exit(1);

    }

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

        if (conn < 0){

            printf("Connect failed.");

            exit(1);

        }

        printf("A new connection from %s:%d\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);

        int temp = pthread_create(&thread, NULL, onServerRecv, &conn);

        if (temp < 0){

            printf("Create thread failed.\n");

            exit(1);

        }

    }

    close(server);

    return 0;

}

由于使用了线程库,编译的时候需要加上库选项:

gcc myserver.c -lpthread

5.      telnet连接Linux板卡,发送字符串来显示。

首先查看telnet是否可以正常执行:

由于放在一个路由器下,连接比较简单。连接成功,发送消息后,可以在led显示屏上看到输出(这之前需要如lab7一样安装内核模块):

可以看到连续显示了1234,实验成功。