前言
本次實(shí)驗(yàn)延續(xù)上次實(shí)驗(yàn)的環(huán)境,使用MAX7219驅(qū)動8x8點(diǎn)陣。上位機(jī)使用Ubuntu 14.04,下位機(jī)使用Raspberry pi 2。
使用的還是上次實(shí)驗(yàn)編譯好的非阻塞式寫入點(diǎn)陣支持內(nèi)核模塊。
這次的實(shí)驗(yàn)跟計(jì)網(wǎng)實(shí)驗(yàn)好像啊好像啊。
控制點(diǎn)陣顯示字符
通過write函數(shù)向device寫入數(shù)據(jù)即可。
#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;
}
編寫網(wǎng)絡(luò)程序接受TCP請求
使用linux下的socket編程,接受外部TCP請求,并將其發(fā)送來的所有數(shù)據(jù)寫入matrix設(shè)備即可實(shí)現(xiàn)顯示功能。

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);
}
// 建立服務(wù)器
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);
// 對連入的連接進(jìn)行處理
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);
// 處理連接發(fā)送過來的字符
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;
}
// 將接收到的所有字符發(fā)送給matrix進(jìn)行顯示
write(Matrix, receiveBuf, count);
}
}
close(server);
return 0;
}

樹莓派本地連入

上位機(jī)遠(yuǎn)程連入
使用線程處理多個連接
上一節(jié)的程序使用的是阻塞式的處理連接,這將導(dǎo)致服務(wù)器每次accept了一個連接之后,無法再處理其余連接。
而這種情況的處理方式有很多。可以使用一個線程對應(yīng)一個socket fd的方式進(jìn)行阻塞式監(jiān)聽。也可以使用IO多路復(fù)用,如select、poll、epoll,在單線程的環(huán)境下進(jìn)行高效的網(wǎng)絡(luò)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);
}
}
…………
}
在這個版本中,主程序只負(fù)責(zé)接受連接,而接受到的連接交由子線程進(jìn)行監(jiān)聽處理。