第一篇:嵌入式串口和網絡編程實驗報告
嵌入式實驗報告
題目:linux
串口和網絡編程
一、實驗目的:
1、強化本學期所學的相關的內容。
2、掌握串口相關設置。
3、強化基于TCP網絡傳輸的三次握手。
4、自學Linux線程的使用。
二、實驗內容:
本試驗基于server和client的透明傳輸來實現類似于QQ的聊天功能。
三、實驗過程:
1、linux開發環境的建立
2、嵌入式linux系統的搭建
1>BootLoader的移植
2>linux系統的裁剪與移植 Linux內核裁剪
./make_image生成自己的uImage2638
上電驗證:
3>根文件系統的移植 修改hostname為:whmtt
./mkcramfsdisk_new 生成rootfs_new.cramfs
大小從老師給的40000到37b00(因為有的沒有用到,大小變小了):
上電驗證:
3、客服端編程client.c 相關代碼: #include
#define SERVER_PORT 20000 //設置服務端口
#define CLIENT_PORT((20001+rand())%65536)//設置客戶端端口(隨機)#define BUFFER_SIZE 256 #define LENGTH_OF_LISTEN_QUEUE 10 //可竊聽隊列長為10 #define WELCOME_MESSAGE “welcome to connect the server.”
void usage(char* name){ printf(“usage: %s IpAddrn ” ,name);}
struct sockaddr_in servaddr,cliaddr;int servfd,clifd,length=0;struct sockaddr_in servaddr,cliaddr;socklen_t socklen=sizeof(servaddr);char buf[BUFFER_SIZE],buf2[BUFFER_SIZE];pthread_t tidp,tidp2;int pth;int runflag=0;
void *Thread1(void *arg)/*等待runflag為1,當為1時清空buf,同時接收來自server的數據并輸出。
但當沒有清空,則break.*/ { while(runflag){
memset(buf,0,BUFFER_SIZE);
length=recv(clifd,buf,BUFFER_SIZE,0);
if(strstr(buf,“$”)>0){runflag=0;printf(“stop!n”);break;}
if(length>0)printf(“from server:%s”,buf);
} }
void *Thread2(void *arg)/*等待發送數據給Server*/ { printf(“Please input your words to Server:--$ to stopn”);while(runflag){
memset(buf2,0,BUFFER_SIZE);
scanf(“%s”,buf2);
send(clifd,buf2,strlen(buf2),0);
if(strstr(buf2,“$”)>0){runflag=0;printf(“stop!n”);break;}
} }
int main(int argc, char** argv){ if(argc < 2){
usage(argv[0]);
exit(1);} if((clifd = socket(AF_INET,SOCK_STREAM,0))< 0)//用tcp定義socket {
printf(“ create socket error!n ”);
exit(1);}
srand(time(NULL));// initialize random generator
bzero(& cliaddr, sizeof(cliaddr));cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(CLIENT_PORT);cliaddr.sin_addr.s_addr = htons(INADDR_ANY);
if(bind(clifd,(struct sockaddr*)&cliaddr,sizeof(cliaddr))< 0){
printf(“bind to port %d failure!n ” ,CLIENT_PORT);
exit(1);}//綁定的目的是讓其端口是隨機的,否則端口是自增1 //一般情況下client端不用綁定
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;inet_aton(argv[1], &servaddr.sin_addr);servaddr.sin_port = htons(SERVER_PORT);
if(connect(clifd,(struct sockaddr *)&servaddr, socklen)< 0){
printf(“can't connect to %s!n”, argv[1]);
exit(1);}
runflag=1;
pth=pthread_create(&tidp,NULL,Thread1,NULL);
if(pth!=0){printf(“error!”);return-1;}
pth=pthread_create(&tidp2,NULL,Thread2,NULL);
if(pth!=0){printf(“error!”);return-1;}
pthread_detach(tidp);
pthread_detach(tidp2);
while(runflag){;}
close(clifd);
return 0;}
4、服務端server.c編寫
相關代碼: #include #define COM0 0 #define BLOCK_MODE 1 #define NONBLK_MODE 0 #define SERVER_PORT 20000 #define LENGTH_OF_LISTEN_QUEUE 10 #define QUEUE 20 #define BUFFER_SIZE 256 #define WELCOME_MESSAGE “welcome to connect the server.” static struct termios g_newtio,g_oldtio; static int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; static int name_arr[] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; int Init_COM(int Comm,int Baudrate,int Parity,int Stopbit,int Flagblock){ int ret,i;char dev_buf[16]; if(Comm > 3){ printf(“Com%d not existn”,Comm); return-1;} memset(dev_buf,0x00,sizeof(dev_buf));sprintf(dev_buf,“/dev/ttyS%d”,Comm); if(Flagblock){ ret = open(dev_buf, O_RDWR | O_NOCTTY);//以默認阻塞方式打開 } else { ret = open(dev_buf, O_RDWR | O_NOCTTY | O_NONBLOCK);//以非阻塞方式打開 } if(ret < 0){ printf(“Open ttyS%d failedn”,Comm); return-1; } if(tcgetattr(ret, &g_oldtio)< 0)//保存原先的端口 { printf(“Get Com Parameter Error.n”); return-1;} for(i= 0;i < sizeof(speed_arr)/ sizeof(int);i++){ if(Baudrate == name_arr[i]) { cfsetispeed(&g_newtio,speed_arr[i]);/*設置輸入輸出波特率*/ cfsetospeed(&g_newtio,speed_arr[i]); break; } } if(i>=sizeof(speed_arr)/ sizeof(int)){ printf(“Unsupported Speed!n”); return-1;} switch(Parity){ case 'n': case 'N': g_newtio.c_cflag &= ~PARODD; g_newtio.c_cflag &= ~PARENB; break; case 'o': case 'O': g_newtio.c_cflag |= PARENB; g_newtio.c_cflag |= PARODD;//奇校驗 break; case 'e': case 'E': g_newtio.c_cflag |= PARENB;//偶校驗 g_newtio.c_cflag &= ~PARODD; break; default: printf(“Unsupported Parityn”); return-1;} switch(Stopbit)//設置停止校驗位是為2,否為1.{ case 1: g_newtio.c_cflag &= ~CSTOPB; break; case 2: g_newtio.c_cflag |= CSTOPB; break; default: printf(“Unsupported Stopbit!n”); return-1;} g_newtio.c_iflag = 0;g_newtio.c_oflag = 0;g_newtio.c_lflag = 0; g_newtio.c_cc[VTIME] = 1;//最大等待時間為1*100ms g_newtio.c_cc[VMIN] = 1;//最小讀數為1 g_newtio.c_iflag &= ~INPCK;g_newtio.c_cflag &= ~CRTSCTS;g_newtio.c_cflag &= ~CSIZE;//設置數據位 g_newtio.c_cflag |= CS8;// g_newtio.c_cflag |= CLOCAL;g_newtio.c_cflag |= CREAD; if(tcsetattr(ret, TCSANOW, &g_newtio)!= 0)//激活設置 { printf(“Set Com Parameter Error!n”); return-1;} tcflush(ret, TCIOFLUSH);//刷新輸入輸出緩存 return ret;} //以上為套接字的相關定義 //一下類似與client一樣設置數據接收和發送。 void RestoreComConfiguration(int fd,struct termios *ptios){ if(tcsetattr(fd, TCSANOW, ptios)!= 0){ printf(“Restore Com Parameter Error!n”);} } int fd;char buf[1024],buf2[1024];int servfd,clifd; struct sockaddr_in servaddr,cliaddr;int runflag=0; void *Thread1(void *arg){ printf(“Please input your words to Server:--$ to stopn”);while(runflag){ memset(buf,0,BUFFER_SIZE); read(fd,buf,1024); send(clifd,buf,strlen(buf),0); if(strstr(buf,“$”)>0){runflag=0;printf(“stop!n”);break;} } } void *Thread2(void *arg){ int length=0;while(runflag){char stdstr[1024]=“from client:”; memset(buf2,0,BUFFER_SIZE); length=recv(clifd,buf2,1024,0);if(length>0){ strcat(stdstr,buf2);strcat(stdstr,“n”); if(strstr(buf2,“$”)>0) {runflag=0;printf(“stop!n”);break;} write(fd,stdstr,strlen(stdstr)); } } } void socket_init(void){ if((servfd=socket(AF_INET,SOCK_STREAM,0))<0){printf(“create socket error!n”);exit(1);} bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(SERVER_PORT);servaddr.sin_addr.s_addr=htons(INADDR_ANY);if(bind(servfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0){printf(“bind to port %d failure!n”,SERVER_PORT);exit(1);} if(listen(servfd,QUEUE)<0){printf(“call listen failure!n”);exit(1);} socklen_t length=sizeof(cliaddr);clifd=accept(servfd,(struct sockaddr*)&cliaddr,&length);if(clifd<0){ printf(“error comes when call accept!n”);exit(1);} } int main(int argc,char *argv[]){ fd = Init_COM(COM0,115200,'N',1,BLOCK_MODE);socket_init();pthread_t tidp,tidp2;int pth;if(fd >= 0)RestoreComConfiguration(fd,&g_oldtio); runflag=1; pth=pthread_create(&tidp,NULL,Thread1,NULL); if(pth!=0){printf(“error!”);return-1;} pth=pthread_create(&tidp2,NULL,Thread2,NULL); if(pth!=0){printf(“error!”);return-1;} pthread_detach(tidp); pthread_detach(tidp2); while(runflag){;} close(clifd);close(fd);close(servfd);//全部關閉 return 0;} 編譯結果: 5、nfs掛載 四、實驗結果: 五、心得體會: 實驗一 TCP Socket API程序設計 一、預備知識 1.網絡編程基本概念 網絡上的計算機間的通訊,實質上是網絡中不同主機上的程序之間的通訊。在互聯網中使用IP地址來標識不同的主機,在網絡協議中使用端口號來標識主機上不同進程,即使用(IP地址,端口號)二元組。 套接字(Socket)用于描述IP地址和端口,是一個通信鏈的句柄,通信時一個網絡程序將要傳輸的一段信息寫入它所在主機的Socket中,該Socket通過與網絡接口卡相連的傳輸介質將這段信息發送到另一臺主機的Socket中,以供其他程序使用。 圖1-1 TCP通信流程 2.TCP通信流程 TCP程序是面向連接的,程序運行后,服務器一直處于監聽狀態,客戶端與服務器通信之前必須首先發起連接請求,由服務器接收請求并在雙方之間建立連接后才可以互相通信。 二、實驗目的 1.了解Winsock API編程原理; 2.掌握TCP Socket程序的編寫; 3.了解C/S模式的特點; 4.學會解決實驗中遇到的問題。 三、實驗任務 使用Winsock API相關類實現TCP Socket通信程序,并能成功運行。 四、實驗環境及工具 1.Windows2000/XP/7 2.Visual C++開發平臺 3.Visual Studio2010 五、實驗內容和步驟 參照《Visual C++網絡編程教程》書中81頁,TCP Socket API程序設計。連接: void CChatClientDlg::OnConnect(){ WSADATA wsd; //WSADATA結構 WSAStartup(MAKEWORD(2,2),&wsd); //加載協議,使用Winsock 2.2版 m_client = socket(AF_INET,SOCK_STREAM,0);//創建流式套接字 //服務器地址 sockaddr_in serveraddr; UpdateData(); if(ServerIP.IsBlank()) { AfxMessageBox(“請指定服務器IP!”); return; } if(sPort.IsEmpty()) { AfxMessageBox(“請指定端口!”); return; } //獲取服務器進程的IP和端口 BYTE nFild[4]; CString sIP; ServerIP.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); sIP.Format(“%d.%d.%d.%d”,nFild[0],nFild[1],nFild[2],nFild[3]); //設置服務器地址結構的內容 serveraddr.sin_family = AF_INET; serveraddr.sin_addr.S_un.S_addr = inet_addr(sIP); serveraddr.sin_port = htons(atoi(sPort)); //發起連接須指明要訪問的服務器進程地址,這個地址存儲在serveraddr中 if(connect(m_client,(sockaddr*)&serveraddr,sizeof(serveraddr))!= 0) { MessageBox(“連接失敗”); return; } else { m_ListWords.AddString(“連接服務器成功!”); m_ListWords.SetTopIndex(m_ListWords.GetCount()1); ServerIP.EnableWindow(); ServerPort.EnableWindow(); m_ButtonConnect.EnableWindow(); m_ButtonDisconnect.EnableWindow(false); m_EditWords.EnableWindow(false); m_ButtonSend.EnableWindow(false); m_ButtonExit.EnableWindow();} “發送”按鈕事件過程代碼如下: void CChatClientDlg::OnSend(){ //向服務器發送信息 UpdateData(); if(m_sWords.IsEmpty()) { AfxMessageBox(“發送的消息不能為空!”); return; } //開始發送數據 int i = send(m_client,m_sWords.GetBuffer(0),m_sWords.GetLength(),0); m_ListWords.AddString(“發送:” + m_sWords); m_ListWords.SetTopIndex(m_ListWords.GetCount()1); closesocket(m_client); ServerIP.EnableWindow(); ServerPort.EnableWindow(); m_ButtonConnect.EnableWindow(); m_ButtonDisconnect.EnableWindow(false); m_EditWords.EnableWindow(false); m_ButtonSend.EnableWindow(false); m_ButtonExit.EnableWindow();} “清空”按鈕的事件過程: m_ListWords.ResetContent();“關于”按鈕的事件過程: CAboutDlg dlgAbout;dlgAbout.DoModal(); 服務器端: 開始監聽代碼: void CChatServerDlg::OnListen(){ WSADATA wsd; //WSADATA結構 WSAStartup(MAKEWORD(2,2),&wsd); //加載協議棧,使用Winsock 2.2版 m_server = socket(AF_INET,SOCK_STREAM,0);//創建流式套接字 //將網絡中的事件關聯到窗口的消息函數中,定義消息號為20000,偵測客戶端的連接請求 WSAAsyncSelect(m_server,m_hWnd,20000,FD_ACCEPT); m_client = 0; BYTE nFild[4]; CString sIP; UpdateData(); if(ServerIP.IsBlank()) { AfxMessageBox(“請設置IP地址!”); return; } if(sPort.IsEmpty()) { AfxMessageBox(“請設置監聽端口!”); return; } ServerIP.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); sIP.Format(“%d.%d.%d.%d”,nFild[0],nFild[1],nFild[2],nFild[3]); //服務器地址 sockaddr_in serveraddr; serveraddr.sin_family = AF_INET; serveraddr.sin_addr.S_un.S_addr = inet_addr(sIP); serveraddr.sin_port = htons(atoi(sPort)); //綁定地址 if(bind(m_server,(sockaddr*)&serveraddr,sizeof(serveraddr))) { MessageBox(“綁定地址失敗.”); return; } //監聽開始,服務器等待連接請求的到來 listen(m_server,5); m_ListWords.AddString(“監聽開始:”); m_ListWords.AddString(“地址” + sIP + “ 端口” + sPort); m_ListWords.AddString(“等待客戶端連接??”); //界面完善 m_ListWords.SetTopIndex(m_ListWords.GetCount()-1); ServerIP.EnableWindow(false); ServerPort.EnableWindow(false); m_ButtonListen.EnableWindow(false); m_ButtonStopListen.EnableWindow(); m_ButtonClear.EnableWindow(); m_ButtonExit.EnableWindow(false);} “停止監聽”按鈕事件過程代碼如下: void CChatServerDlg::OnStopListen(){ //停止監聽 closesocket(m_server); m_ListWords.AddString(“停止監聽”); m_ListWords.SetTopIndex(m_ListWords.GetCount()1);} “斷開”按鈕事件過程代碼如下: void CChatServerDlg::OnDisconnect(){ closesocket(m_client); m_ListWords.AddString(“與客戶端斷開”); m_ListWords.SetTopIndex(m_ListWords.GetCount()1); //界面完善 m_ButtonDisconnect.EnableWindow(); m_EditWords.EnableWindow(); m_ButtonSend.EnableWindow();} ReceiveData()函數代碼如下: void CChatServerDlg::ReceiveData(){ //接收客戶端的數據 char buffer[1024]; int num = recv(m_client,buffer,1024,0); buffer[num] = 0; CString sTemp; sTemp.Format(“收到:%s”,buffer); m_ListWords.AddString(sTemp);//顯示信息 m_ListWords.SetTopIndex(m_ListWords.GetCount()1); closesocket(m_client);//關閉與客戶端通信的Socket WSAAsyncSelect(m_server,m_hWnd,20000,FD_ACCEPT);//準備接收新的客戶端連接 //界面完善 m_ButtonDisconnect.EnableWindow(false); m_EditWords.EnableWindow(false); m_ButtonSend.EnableWindow(false);} 服務器的初始化代碼如下: //界面初始化 m_ButtonStopListen.EnableWindow(false);m_ButtonDisconnect.EnableWindow(false);m_ButtonClear.EnableWindow(false);m_EditWords.EnableWindow(false);m_ButtonSend.EnableWindow(false); 運行結果: 六、思考題 1.用Winsock API編程時,主要進行哪些通行的操作步驟? 2.闡述C/S模式的通信過程。答: 1.通行的操作 1.Winsock的打開(WSAStartup())。2.建立套接字(socket()或WSASocket())。3.地址綁定(bind())。 4.服務器監聽連接(listen())。 5.客戶端提出連接申請(connect()或WSAConnect())。6.服務器接收客戶端的連接請求(accept()或WSAAccept())。7.數據的發送(send()或WSASend(),sendto()或WSASendTo())。8.數據的接收(recv()或WSARecv(),recvfrom()或WSARecvfrom())。9.關閉套接字(closesocket())。10.關閉Winsock(WSACleanup())。 2通信過程 華南農業大學 實驗報告 ----------目錄---------- 1、實驗任務和目的..............................................................................................................2、實驗準備..........................................................................................................................3、實驗步驟................................................................................................................................4、實驗分析與總結....................................................................................................................(1)、分析.............................................................................................................................(2)、總結.............................................................................................................................1、實驗任務和目的 了解串行通信的背景知識后,通過三線制制作一條串口通信線(PC-PC),并編程實現兩臺PC間通過RS-232C通信。要求兩臺PC機能進行實時的字符通信,并了解工業自動化控制中的基本通信方式。 2、實驗準備 1、檢查PC是否具有串行通信接口,并按其針腳類準備一條串口通信線纜。 2、串口包的安裝,下載javacomm20-win32.zip并解壓,將win32com.dll復制到 3、實驗步驟 1、將實驗所需RS-232纜線準備好,并將JAVA串口包復制到相應地目錄下。 2、查找有關串口通信的書籍以及在網上查找相應地串口通信代碼。 3、用JAVA編程軟件JCreator編寫代碼。 4、實驗分析與總結 (1)、分析 (I)、對串口讀寫之前需要先打開一個串口并檢測串口是否被占用: public void open(){//打開串口以及輸入輸出流 recieve=false; try {serialPort=(SerialPort)portId.open(“Serial Communication”, 2000);} catch(PortInUseException e){System.out.println(“端口正被占用!”);} try {serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);} catch(UnsupportedCommOperationException e){System.out.println(“不支持通信”);} try { outputStream=serialPort.getOutputStream(); inputStream=serialPort.getInputStream(); 1-完整運行程序如圖所示: 圖1 (2)、總結 通過本次串口實驗,我對串口通信的知識了解的更透徹,這是在剛開始對串口通信知識不了解的情況下就編程而造成許多錯誤之后才得到的結果。在網上查找資料的時候也接觸到了不少其他的編程語言例如VB,delphi,C#等,這也讓我對這些從沒有學過的語言有所了解,我想這些知識對以后的實驗工作都有幫助。 3-- 網絡編程與實踐實驗報告 實驗內容:串口通信編程 學號:S201502189 姓名:職榮豪 日期:2015-9-28 一、實驗要求 使用VS2010編寫基于對話框的MFC應用程序,兩個窗口分別使用兩個串口,使得這兩個窗口可以進行通信,包括數據的發送與接收。 二、實驗原理 本實驗使用Microsoft Communications Control控件,利用這個ActiveX控件,只需要編寫少量代碼即可輕松進行通信。 該控件相關的函數如下: put__CommPort:設置串口號 put_Settings:以字符串的形式設置波特率、奇偶校驗位(n-無校驗,e-偶校驗,o-奇校驗)、數據位數、停止位數 put_InputMode:設置接收數據的類型(0-文本類型,1-二進制類型)put_InputLen:設置從接收緩沖區讀取的字節數,0表示全部讀取 put_InBufferSize:設置接收緩沖區大小 put_OutBufferSize:設置發送緩沖區大小 put_RThreshold:設定當接收幾個字符時觸發OnComm事件,0表示不產生事件,1表示每接收一個字符就產生一個事件 put_SThreshold:設定在觸發OnComm事件前,發送緩沖區內所允許的最少的字符數,0表示發送數據時不產生事件,1表示當發送緩沖區空時產生OnComm事件 put_PortOpen:打開或關閉串口,傳入參數為true時打開串口,傳入參數為false時關閉串口 get_CommEvent:獲得串口上剛發生的事件,事件值為2表示接收到數據 get_InBufferCount:獲得緩沖區中的數據位數 get_Input:獲取緩沖區數據,返回類型為VARIANT put_Output:發送數據 三、設計思路 需要添加一個Microsoft Communications Control控件,用于進行串口通信。由于要求同一程序可運行兩個窗口進行相互通信,需要兩個窗口開啟兩個不同串口,故需要添加一個Edit Control控件用于輸入串口號,并添加打開串口按鈕,在點擊該按鈕時對串口控件的參數進行設置并開啟串口。同時添加關閉串口按鈕,點擊后關閉串口并可以對串口號進行修改。 需要添加兩個Edit Control 分別用于顯示接收到的數據以及輸入要發送的數據。需要添加一個發送按鈕,點擊后發送輸入的數據。 四、實驗步驟 1.建立基于對話框的MFC應用程序 2.添加界面控件并設置ID與Caption 添加Microsoft Communications Control控件,用于進行串口通信 添加一個Edit Control控件,用于輸入串口號,ID設置為IDC_PORT 添加一個Static Text控件,用于標注端口號,將Caption設置為“串口號:” 添加兩個按鈕,分別用于打開串口、關閉串口。IDC分別設置為IDC_BTN_OPEN、IDC_BTN_CLOSE,Caption分別設置為“打開”、“關閉” 添加兩個Edit Control,分別用于顯示接收到的數據以及輸入要發送的數據,ID分別設置為IDC_RECEIVE、IDC_SEND 添加兩個Static Text控件,用于標注接收區與發送區,Caption分別設置為“接收區”、“發送區” 添加一個按鈕用于發送數據,ID設置為IDC_BTN_SEND,Caption設置為“發送” 調整控件的大小與位置。 完成后如圖: 3.給控件綁定變量 右鍵單擊Microsoft Communications Control控件,選擇“添加變量”,變量名為m_com 打開類向導給控件添加變量: 給IDC_PORT綁定變量,用于存放輸入的端口號,數據類型為int,變量名為m_port 給IDC_RECEIVE綁定變量,用于存放接收到的數據,數據類型為CString,變量名為m_strReceive 給IDC_SEND綁定變量,用于存放輸入的待發送的數據,數據類型為CString,變量名為m_strSend 4.給控件添加事件響應函數 右鍵單擊Microsoft Communications Control控件,選擇“添加事件處理程序”,點擊“添加編輯”,生成響應函數,此函數用于接收數據。 在函數中添加以下代碼: UpdateData(TRUE);if(nEvent == 2){ } UpdateData(FALSE);//將m_strReceive的值顯示到控件中 //更新m_strReceive的值 //獲取事件值 //獲取緩沖區位數 //時間值為2,此時為收到數據 int nEvent = m_com.get_CommEvent();int k = m_com.get_InBufferCount();if(k <= 0)//位數小于等于0時則返回 return;char* str =(char*)m_com.get_Input().parray->pvData;//獲取接收到數據的字*(str + k)= '
主站蜘蛛池模板:
国产在线视频一区二区三区欧美图片|
久久久亚洲欧洲日产国码aⅴ|
亚洲人成毛片在线播放|
99久久99久久精品国产片|
国产欧美性成人精品午夜|
久久久久无码精品国产人妻无码|
成人性生交大片免费看vr|
藏春阁福利视频|
无码综合天天久久综合网|
狼友网精品视频在线观看|
海角社区在线视频播放观看|
国产一区内射最近更新|
色婷婷综合久久久久中文字幕|
精品麻豆一卡2卡三卡4卡乱码|
蜜芽国产尤物av尤物在线看|
麻豆一区产品精品蜜桃的广告语|
极品少妇一区二区三区四区|
天天爽夜夜爱|
亚洲蜜桃精久久久久久久久久久久|
国产精品久久国产精麻豆99网站|
久久久久久国产精品mv|
青青草国产三级精品三级|
熟妇人妻不卡中文字幕|
中文字幕精品一区二区精品|
蜜臀色欲av在线播放国产日韩|
国产三级在线观看播放|
aⅴ亚洲 日韩 色 图网站 播放|
y111111少妇影院无码|
国产成人亚洲综合无码99|
夜夜高潮夜夜爽夜夜爱爱一区|
亚洲国产日韩欧美综合a|
尤物yw午夜国产精品视频|
55夜色66夜色国产精品视频|
国产草草影院ccyycom|
婷婷婷国产在线视频|
精品无码国产不卡在线观看|
亚洲中文字幕久久精品无码a|
亚洲精品乱码久久久久久久久久久久|
伊人久久综合狼伊人久久|
久碰久摸久看视频在线观看|
扒开女人内裤猛进猛出免费视频|
第二篇:網絡編程實驗報告
第三篇:串口通信實驗報告范文
第四篇:串口通訊實驗報告