日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

uclinux多线程应用-网络通信[转]

發布時間:2023/12/15 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uclinux多线程应用-网络通信[转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數據通信是依照一定的協議,利用數據傳輸技術在兩個終端之間傳遞數據信息的一種通信技術。它可以實現計算機和計算機、計算機和終端以及終端和終端之間的數據信息傳遞。根據通信方式的不同可以分成并行通信和串行通信。在工業控制領域,成千上萬的具有串行接口的工業設備,如檢測器、感應器、PLC、讀卡器等,它們無時無刻地采集現場數據,并且想換之間通過串口連接成一個控制網絡,作為信息系統內管理數據的工具。串行通信技術作為一種靈活、方便、可靠的通信方式,長久以來一直穩定的應用在IT和工業通信領域。近年來,隨著互聯網技術的蓬勃發展,串行通信技術面臨著新的挑戰和發展空間。
由于串口通信存在的數據量小、布線困難、傳輸距離短的特點,我們需要一個更好的解決辦法,近年來出現的交換以太網克服了這些缺點。這里我們設計一個嵌入式串口協議處理系統,來實現串口與網口數據間的傳輸。說白了,就是把從串口讀取到的數據發向網絡,把從網絡讀取到的數據發向串口。在系統發送和接受以太網數據的時候,需要在這之前建立連接。并且由于在實現網絡數據傳向串口和串口數據發向網絡的過程是同時進行,這就需要用到多線程技術。對于串口通信和TCP/IP協議就不過多介紹,下面直接講如何做一些簡單的編程,需要有一點C語言基礎。
Linux系統下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時需要使用庫libpthread.a(dl注:在Makefile里添加LDLIBS += -lpthread即可)。

#include <pthread.h>
在根據前面的介紹分別實現了串口轉網絡和網絡串口功能以后,下面需要把兩個功能分別添加進各自的線程。這里分別命名為task和task2。
void task(int *counter);
void task2(int *counter);
用函數pthread_create來創建一個線程,返回0則表示創建成功:
pthread_create( &thrd , NULL , (void*) task , (void*) & gCounter );
用pthread_join等待線程結束(當然程序中是要讓線程無限循環的):
pthread_join(thrd,NULL);?
???? 當面這些都實現以后,在Linux下編譯,生成目標文件,下載到開發板準備運行。
由于μClinux攜帶了RTL8019驅動和TCP/IP協議,因此,在μClinux下實現網絡功能就顯得比較的簡單。
服務器端的程序:
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)?????? //UDP方式
{
???? printf("ERROR:Cannot obtain Socket Descriptor!\n");
????????? return(0);
}
addr_local.sin_family=AF_INET;????????????????????
addr_local.sin_port=htons(PORT);

addr_local.sin_addr.s_addr=INADDR_ANY;
if(bind(sockfd,(struct sockaddr *)&addr_local,sizeof(struct sockaddr)) == -1)
{
printf("ERROR:Cannot bind port %d\n !",PORT);
return (0);
???????? }
else
???????? {
????????? printf("OK:Bind successfully!\n");
???????? }
sin_size=sizeof(struct sockaddr);
num=recvfrom( sockfd , revbuf , sizeof ( revbuf ) , 0 ,
( struct sockaddr* ) & addr_remote, &sin_size );
if(num<0)
{
???????? }
else
???????? {
write(fd,revbuf,num);
printf("\n");
}
?? 客戶端程序:
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)?????? //UDP方式
{
????? printf("ERROR:Cannot obtain Socket Descriptor!\n");
????????? return(0);
}
addr_remote.sin_family=AF_INET;
addr_remote.sin_port=htons(PORT);???????????????????

addr_remote.sin_addr.s_addr=inet_addr((const char*)m_strServer);
size=read(fd,revbuf,8);
if(size>0)
{
num=sendto(sockfd,revbuf,size,0,(struct sockaddr * )&addr_remote,sizeof(struct sockaddr_in));
if(num<0)
{
????????????????? printf("ERROR:Cannot send your data!\n");
}
else
??????????? {
???????????????? printf("OK,Sent Success");
??????????? }
}
在μClinux下的串口實現,由于它已經帶了串口的驅動程序,只需要在應用的時候將其打開就可以。這里,我們使用默認的115200Hz的頻率,8位數據位,無奇偶校驗,1位停止位,無數據流控制。
代碼如下:
int fd;
fd=open("/dev/ttyS0",O_RDWR);
其中open函數表示打開設備文件,因為Linux是以文件方式管理設備的,要打開一個設備,只需要用打開文件的函數就可以了。而串口在Linux里位于dev文件夾下,串口0、串口1依次對應ttyS0、ttyS1。O_RDWR表示以可讀寫方式打開設備。fd存儲設備號,如所有欲檢查的權限都通過了則返回0值,表示成功,只要有一個權限被禁止則返回-1。
同樣的,將數據寫入串口的話,我們使用write函數:
int fd;
write(fd,buf,num);
這里fd表示已經打開的設備號,這里是串口0,buf表示需要發送的數據,而num則表示發送的數據量。如果發送失敗則返回-1,錯誤代碼寫人errno中。如果write順利,則返回實際寫入的字節數。
好了,上面的一些解釋介紹,下面的完整的源代碼:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT??????? 5000??????????? //通信端口
#define LENGTH????? 64????????????? //緩存大小
void task(int *counter);?????????? //task:ser2udp
void task2(int *counter);????????? //task2:udp2ser
int gCounter = 0;?????????????????
int gCounter2 = 0;
//task的變量
int size;
int sockfd;?????????????????????????
int num;????????????????????????????????
char revbuf[LENGTH];
//task2的變量
int size2;??????????????????????
int num2;?????????????????????????????
char revbuf2[LENGTH];
//變量
int fd;
char m_strServer[]="192.168.0.10";????? //PC的IP?
struct sockaddr_in addr_local;
struct sockaddr_in addr_remote;?
int main(void)
{
pthread_t thrd,thrd2;
int result;
//¥úo(TM)0
if((fd=open("/dev/ttyS0",O_RDWR))==-1)
{
printf("ERROR:can not open COM0\n");
return (0);
}
else
{
printf("Success open COM0\n");
}
//ser2udp
addr_remote.sin_family=AF_INET;??????? //UDP
addr_remote.sin_port=htons(PORT);????????????????? //填入端口
addr_remote.sin_addr.s_addr=inet_addr((const char*)m_strServer);?? //目標IP
//udp2ser
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
??????? printf("ERROR:Cannot obtain Socket Descriptor!\n");
return(0);
??????? }
addr_local.sin_family=AF_INET;????????????????????
addr_local.sin_port=htons(PORT);?????????????????
addr_local.sin_addr.s_addr=INADDR_ANY;????????????
if(bind( sockfd,(struct sockaddr *)&addr_local,sizeof(struct sockaddr))==-1)
{
printf("ERROR:Cannot bind port %d\n !",PORT);
return (0);
}
else
{
printf("OK:Bind successfully!\n");
}
size2 = sizeof(struct sockaddr);
fprintf(stderr,"hello world\n");

//創建task
result = pthread_create(&thrd,NULL,(void*)task,(void*)&gCounter);????
if (result)
{
perror("pthread create fail");
exit(0);
}
//創建task2
result = pthread_create(&thrd2,NULL,(void*)task2,(void*)&gCounter2);?
if (result)
{
perror("pthread create fail");
exit(0);
}
pthread_join(thrd,NULL);???????? //等待task結束
return 0;
}
//?flser2udp
void task(int *counter)
{
printf("hello world from pthread1!\n");
while(1)
{
??????? size=read(fd,revbuf,8);???????????? //從串口讀取數據
??????? if(size>0)????????????????????????? //size里是讀取到的數據量
{?
?????????????? //發向網絡
num=sendto(sockfd,revbuf,size,0,
(struct sockaddr * )&addr_remote,sizeof(struct sockaddr_in));???
?????????????? //發送失敗
if(num<0)??????????????????????????????????????????
{
??????? printf("ERROR:Cannot send your dta!\n");
??????? }
else
??????? {
??????? }
}
}
}
//task2:udp2ser
void task2(int *counter)
{
printf("hello world from pthread2!\n");
while(1)
{?
//等待網絡數據
num2=recvfrom(sockfd,revbuf2,sizeof(revbuf2),0,
(struct sockaddr * )&addr_remote,&size2);?
if(num2<0)??????????????????? //獲取失敗??????????????????
{
}
else???????????????????????????????????????????????
{
write(fd,revbuf2,num2);????? //寫入串口
printf("\n");
}
}
}
好了,按照上面的步驟編譯運行,然后同時打開SSCOM3.2和網絡調試助手,都設置成定時發送模式,我都設置成10ms,二者不斷發送接收數據,測試了一下,在一個局域網內,數據的丟失量的非常小的。

總結

以上是生活随笔為你收集整理的uclinux多线程应用-网络通信[转]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。