<del id="dhfrq"></del>

    1. <tr id="dhfrq"></tr>
      成人午夜激情在线观看,国产精品一线天粉嫩av,99精品国产综合久久久久五月天 ,一卡2卡三卡4卡免费网站,国产高清在线男人的天堂,五月天国产成人AV免费观看,67194熟妇在线观看线路,成人无码潮喷在线观看
      現在位置:范文先生網>理工論文>計算機論文>C語言實的串行通信接口程序

      C語言實的串行通信接口程序

      時間:2023-02-20 22:50:18 計算機論文 我要投稿
      • 相關推薦

      C語言實的串行通信接口程序

         摘 要 該文介紹了Sockets通信原理,從程序員角度著重討論了Windows Sockets為支持異步通信對Sockets的功能擴充,并給出了應用Windows Sockets實現網絡實時通信的一個程序實例。關
      IBM公司于1994年4月推出的TCP/IP for DOS V2.1.1所提供的開發軟件包Programmer's Tool Kit不僅帶有DOS下網絡編程接口,而且提供了Windows下網絡異步通信接口WINSOCK。
      一、Socket網絡編程原理Socket是BSD UNIX提供的網絡應用編程接口,它采用客戶機/服務器的通信機制,使網絡客戶機方和服務器方通過Socket實現網絡之間的連接和數據交換。Socket提供了一系列的系統調用,使用這些系統調用可以實現TCP、UDP、ICMP和IP等多種網絡協議之間的通信。
      Socket有三種主要類型:stream sockets,datagram sockets和raw sockets。Streamsocket接口定義了一種可靠的面向連接的服務,它實現了無差錯無重復的順序數據傳輸。它通過內置的流量控制解決了數據的擁塞,應用程序可以發送任意長度的數據,將數據當作字節流。Datagram socket接口定義了一種無連接的服務,數據通過相互獨立的包進行傳輸,包的傳輸是無序的,并且不保證是否出錯、丟失和重復。包長度是有限的(隱含長度為8192字節,最大長度可設為32768字節)。Raw socket接口允許對低層協議如IP和ICMP的直接存取,它主要用于新的網絡協議實現的測試等。
      下面我們通過一個面向連接的傳輸發生的典型情況來說明socket網絡通信的實現。
      由圖我們可以看出,客戶機和服務器的關系不是對稱的。服務器首先啟動,然后在某一時間啟動客戶機與服務器建立連接。服務器和客戶機開始都必須用調用socket ()建立一個套接字(socket),然后服務器調用bind()將套接字與一個本地網絡地址捆扎在一起,再用調用listen()使套接字處于一種被動的準備接收狀態,同時規定它的請求隊列長度,之后服務器就可以調用accept()來接收連接了。客戶機在建立套接字之后,便可以通過調用connect()和服務器建立連接。連接建立后,客戶機和服務器之間就可以通過連接發送和接收數據(調用read()和write())。最后,待數據傳送結束,雙方調用close()關閉套接字。
      @@T8S10700.GIF;面向連接的協議實現的Socket調用圖@@
      二、WINSOCK對Socket的擴充
      BSD Socket支持阻塞(blocking)和非阻塞(non-blocking)兩種工作方式。在阻塞方式下,connect()、accept()、read()和recv()等調用在執行時都處于阻塞狀態直到它成功或出錯返回。在非阻塞方式下,這些調用是立即返回的,但是它們是否完成得靠查詢才能知道。對于Windows這種非搶先多任務操作系統來說,這兩種工作方式都是難以接受的,為此,WINSOCK在盡量與BSD Socket保持一致的前提下,又對它作了必要的擴充。
      WINSOCK對BSD Socket的擴充主要是在基于消息、對網絡事件的異步存取接口上。表1列出了WINSOCK擴充的函數功能。
      從表1可以看出,WINSOCK的擴充功能可以分為如下幾類。
      (1)異步選擇機制
      異步選擇函數WSAAsyncSelect()允許應用程序提名一個或多個感興趣的網絡事件,所有非阻塞的網絡I/O例程(如send()和resv()),不管它是已經使用還是即將使用,都可作為WSAAsyncSelect()函數選擇的候選。當被提名的網絡事件發生時,Windows應用程序的窗口函數將收到一個消息,消息附帶的參數指示被提名過的某一網絡事件。
      @@T8S10701.GIF;表1 WINSOCK擴充函數功能@@
      (2)異步請求例程
      異步請求例程允許應用程序用異步方式獲取請求的信息,如WSAAsyncGetXByY()類函數允許用戶請求異步服務,這些功能在使用標準Berkeley函數時是阻塞的。函數WSACancelAsyncRequest()允許用戶終止一個正在執行的異步請求。
      (3)阻塞處理方法
      WINSOCK在調用處于阻塞時進入一個叫“Hook”的例程,它負責處理Windows消息,使得Windows的消息循環能夠繼續。WINSOCK還提供了兩個函數(WSASetBlockingHook()和WSAUnhookBlockingHook())讓用戶能夠設置和取消自己的阻塞處理例程。另外,函數WSAIsBlocking()可以檢測調用是否阻塞,函數WSACancelBlockingCall()可以取消一個阻塞的調用。
      (4)出錯處理
      為了和以后的多線索環境(如Windows NT)兼容,WINSOCK提供了兩個出錯處理函數WSAGetLastError()和WSASetLastError()來獲取和設置本線索的最近錯誤號。
      (5)啟動與終止
      WINSOCK的應用程序在使用上述WINSOCK函數前,必須先調用WSAStartup()函數對Windows Sockets DLL進行初始化,以協商WINSOCK的版本支持,并分配必要的資源。在應用程序退出之前,應該先調用函數WSACleanup()終止對Windows Sockets DLL的使用,并釋放資源,以利下一次使用。
      在這些函數中,實現Windows網絡實時通信的關鍵是異步選擇函數WSAAsyncSelect()的使用,其原型如下:int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd, unsigned intwMsg, long lEvent);它請求Windows Sockets DLL在檢測到在套接字s上發生的lEvent事件時,向窗口hWnd發送一個消息wMsg。它自動地設置套接字s處于非阻塞工作方式。參數lEvent由表2所列事件的一個或多個組成。
      @@T8S10702.GIF;表2 異步選擇網絡事件@@
      例如,我們要在套接字s讀準備好或寫準備好時接到通知,可以使用下面的語句:
      rc=WSAAsyncSelect(s,hWnd,wMsg,FD-READ | FD-WRITE);
      當套接字s上被提名的一個網絡事件發生時,窗口hWnd將收到消息wMsg,變量lParam的低字指示網絡發生的事件,高字指示錯誤碼。應用程序就可以通過這些信息來決定自己的下一步動作。
      三、網絡實時通信的實現
      我們來設計一個簡單的基于連接的點對點網絡實時通信程序。服務器首先啟動,它建立套接字之后等待客戶機的連接;客戶機在啟動后,建立套接字,然后和服務器建立連接;連接建立后,客戶機通過連接給服務器發送一段數據,服務器接收后又將它發送回來,客戶機再發送,如此循環,直至用戶命令客戶機退出或網絡出錯;客戶機關閉連接和套接字后退出,服務

      器在檢測到連接關閉后,關閉套接字自動結束。
      我們的實例是UNIX下基于BSD Socket的服務器程序和Windows下基于WINSOCK的客戶機程序之間的通信。服務器在主機UNIX下直接運行,前臺和后臺均可;客戶機在Windows下運行,帶一個參數,即主機的名字。如win client rs6000,rs6000是在HOSTS文件中已定義好的主機名。
      我們先看客戶機程序,首先定義幾個宏、菜單資源和部分全局變量。
      程序1:部分Windows程序源代碼(宏、菜單和變量)
      #define USERPORT 3333/*用戶定義端口號*/
      #define IDM-START101/*“啟動”菜單項標志*/
      #define IDM-EXIT102/*“退出”菜單項標志*/
      #define UM-SOCKWM-USER+0x100/*用戶定義網絡消息*/
      ClientMenu MENU/*客戶機菜單*/
      BEGIN
      POPUP "&Server"
      BEGIN
      MENUITEM "&Start...", IDM-START
      MENUITEM "&Stop",IDM-STOP
      END
      END
      #include <winsock.h>/*必須包含winsock.h頭文件*/
      HANDLEhInst;
      charserver-address = {0};/*服務器地址緩沖區*/
      charbuffer;/*接收發送緩沖區*/
      char FAR *lpBuffer=&buffer;
      SOCKETs=0;/*套接字*/
      struct sockaddr-in dst-addr;/*目標地址*/
      struct hostent *hostaddr;/*主機地址*/
      struct hostent hostnm;
      intcount=0;/*發送接收循環計數器*/
      客戶機程序的窗口主函數很簡單,它在注冊窗口類、建立窗口后,只是給主窗口函數發送一個用戶消息,然后就進入Windows消息處理循環。
      程序2:部分Windows程序源代碼(窗口主函數)
      int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lp
      CmdL
      ine, int nCmdShow)
      {
      HWND hWnd;
      MSGmsg;
      lstrcpy((LPSTR) server-address, lpCmdLine);/*取主機名字*/
      if (!hPrevInstance)
      if (!InitApplication(hInstance))
      return (FALSE);
      hInst=hInstance;
      hWnd=CreateWindow("ClientClass","Windows ECHO Client",
      WS-OVERLAPPEDWINDOW,CW-USEDEFAULT,CW-USEDEFAULT,
      CW-USEDEFAULT,CW-USEDEFAULT,
      NULL,NULL,hInstance,NULL);
      if (!hWnd)
      return (FALSE);
      ShowWindow(hWnd,nCmdShow);
      UpdateWindow(hWnd);
      /*給主窗口函數發送WM-USER消息*/
      PostMessage(hWnd,WM-USER,(WPARAM) 0,(LPARAM) 0);
      while (GetMessage(&msg,NULL,NULL,NULL)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      }
      return (msg.wParam);
      }
      主窗口函數ClientProc是程序的主要部分,它處理相關的消息:在接到消息WM-USER后,它調用函數WSAStartup()初始化Windows Sockets DLL,并檢查其版本號,然后通過主機名獲取主機地址;在接到消息WM-COMMAND時,如果是命令IDM-START,則調用子程序Client()建立套接字,并試圖和服務器建立連接,如果是命令IDM-STOP,則調用函數WSACleanup()終止Windows Sockets DLL,并發出終止應用程序的消息;在接到消息UM-SOCK時,它根據參數lParam指示的網絡事件,進行相應的操作,然后選擇下一個期望的網絡事件。
      程序3:部分Windows程序源代碼(主窗口函數)
      long FAR PASCAL
      ClientProc(HWND hWnd, unsigned message, UINT wParam, LONG lParam)
      {
      int length,i;
      WSADATAwsaData;/*描述Windows Sockets實現細節的數據結構*/
      intStatus;
      switch (message) {
      case WM-USER:
      Status=WSAStartup(0x101,&wsaData);
      if (Status !=0) {
      AlertUser(hWnd,"WSAStartup() failed");
      PostQuitMessage(0);
      }
      if (LOBYTE(wsaData.wVersion) !=1 || HIBYTE(wsaData.wVersion) !=1)
      { /*現在支持的版本是WINSOCK.DLL 1.1*/
      AlertUser(hWnd, "WSAStartup() Version not match");
      WSACleanup();
      PostQuitMessage(0);
      }
      hostaddr=gethostbyname(server-address);
      if (hostaddr==NULL) {
      AlertUser(hWnd, "gethostbyname ERROR ");
      WSACleanup ();
      PostQuitMessage(0);
      }
      memcpy(&hostnm,hostaddr,sizeof(struct hostent));
      break;
      case WM-COMMAND:
      switch (wParam) {
      case IDM-START:
      if (!Client(hWnd)) {
      closesocket(s);
      AlertUser(hWnd, "Start Failed");
      }
      break;
      case IDM-

      STOP:
      WSACleanup();
      PostQuitMessage(0);
      break;
      }
      break;
      case UM-SOCK:
      switch (lParam) {
      case FD-CONNECT:/*網絡事件:連接建立*/
      if (!set-select(hWnd, FD-WRITE))/*選擇:期望發送*/
      closesocket(s);
      break;
      case FD-READ:/*網絡事件:讀準備好*/
      if (!receive-pkt(hWnd)) {/*接收數據*/
      AlertUser(hWnd, "Receive Packet Failed");
      closesocket(s);
      break;
      }
      if (!set-select(hWnd, FD-WRITE))/*選擇:期望發送*/
      closesocket(s);
      break;
      case FD-WRITE:/*網絡事件:寫準備好*/
      for (i=0;i<1024;i++)
      buffer=(char) 'A'+i % 26;
      length=1024;
      if (!(send-pkt(hWnd,length))) {/*發送數據*/
      AlertUser(hWnd, "Packet Send Failed");
      closesocket(s);
      break;
      }
      if (!set-select(hWnd, FD-READ)) /*選擇:期望接收*/
      closesocket(s);
      break;
      case FD-CLOSE:/*網絡事件:連接關閉。操作:停止異步選擇*/
      if (WSAAsyncSelect(s,hWnd,0,0)==SOCKET-ERROR)
      AlertUser(hWnd, "WSAAsyncSelect Failed");
      AlertUser(hWnd, "Socket has been closed");
      break;
      default:/*網絡出錯則警告,其他事件忽略*/
      if (WSAGETSELECTERROR(1Param) !=0) {
      AlertUser(hWnd, "Socket Report Failure");
      closesocket(s);
      break;
      }
      break;
      }
      break;
      case WM-DESTROY:
      closesocket(s);/*關閉窗口前應該關閉套接字,并*/
      WSACleanup();/*終止Windows Sockets DLL*/
      PostQuitMessage(0);
      break;
      default:
      return (DefWindowProc(hWnd, message,
      wParam, lParam));
      }
      return (NULL);
      }
      程序4:部分Windows程序源代碼(子程序)
      BOOL Client(HWND hWnd)/*客戶機子程序*/
      {
      if (!make-skt(hWnd))/*建立套接字*/
      return(FALSE);
      if (!set-select(hWnd,FD-CONNECT))/*設置異步連接*/
      return(FALSE);
      if (!connect-skt(hWnd))/*建立連接*/
      return(FALSE);
      return(TRUE);
      }
      BOOL receive-pkt(HWND hWnd)/*接收數據子程序*/
      {
      HDC dc;
      intlength;
      int11,12,13;
      charlinel,line2,line3;
      count ++;/*循環計數器加1*/
      if ((length=recv(s,lpBuffer,1024,0))==SOCKET-ERROR)
      return(FALSE); /*如果接收數據出錯,則返回FALSE*/
      if (length==0) /*接收數據長度為零,表示連接中斷*/
      return(FALSE);
      if (dc=GetDC(hWnd)) { /*接收數據成功,顯示信息*/
      11=wsprintf((LPSTR) line1,"TCP Echo Client No.%d",count);
      12=wsprintf((LPSTR) line2,"Received %d bytes", length);
      13=wsprintf((LPSTR) line3,"Those are:%c,%c,%c,%c,%c,%c",
      buffer,buffer,buffer,buffer,buffer,buffer
      );
      TextOut(dc, 10, 2, (LPSTR) linel, 11);
      TextOut(dc, 10, 22, (LPSTR) line2, 12);
      TextOut(dc, 10, 42, (LPSTR) line3, 13);
      ReleaseDC(hWnd, dc);
      }
      return(TRUE);
      }
      BOOL set-select(HWND hWnd, long lEvent)/*異步選擇子程序*/
      {
      if (WSAAsyncSelect(s,hWnd, UM-SOCK, lEvent)==SOCKET-ERROR) {
      AlertUser(hWnd, "WSAAsyncSelect Failed");
      return (FALSE);
      }
      return (TRUE);
      }
      BOOL make-skt(HWND hWnd)/*建立套接字子程序*/
      {
      if ((s=socket(AF-INET,sock-type,0))==INVALID-SOCKET) {
      AlertUser(hWnd, "Socket Failed");
      return (FALSE);
      }
      return (TRUE);
      }
      BOOL connect-skt(HWND hWnd)/*建立連接子程序*/
      {
      memset((void*) &dst-addr, sizeof(dst-addr),0);
      dst-addr.sin-family=AF-INET;
      dst-addr.sin-port=htons(USERPORT);
      dst-addr.sin-addr.s-addr=*((unsigned long *)hostnm.h-addr-list );
      if (connect(s, (stru

      ct sockaddr *) & dst-addr,
      sizeof(dst-addr))==SOCKET-ERROR) {
      AlertUser(hWnd, "Connect Failed");
      return (FALSE);
      }
      return (TRUE);
      }
      BOOL send-pkt(HWND hWnd, int len)/*發送數據子程序*/
      {
      int length;
      if ((length=send(s,lpBuffer,len,0))==SOCKET-ERROR)
      return (FALSE);
      else if (length !=len) {
      AlertUser(hWnd, "Send Length NOT Match!");
      return(FALSE);
      }
      return (TRUE);
      }
      我們用最簡單的語句編制一個UNIX下基于BSD SOCKET的服務器程序,它在建立連接后,只負責將收到的數據發回去,在連接斷開后,服務器關閉套接字返回。要編制在Windows下的服務器程序,可參照客戶機程序,使用WINSOCK的異步選擇機制。
      程序5:UNIX下服務器程序源代碼
      /*TCP/IP必要的頭文件*/
      #include <sys/types.h>
      #include <netinet/in.h>
      #include <sys/socket.h>
      #include <arpa/inet.h>
      #define USERPORT 3333/*用戶定義端口號,與客戶機相同*/
      #define HOST-IP-ADDR "166.111.8.80"/*我們的主機地址*/
      main(int argc, char **argv)
      {
      char buf;/*buffer for sending and receiving data*/
      struct sockaddr-in client;/*client address information*/
      struct sockaddr-in server;/*server address information*/
      int s;/*socket for accepting connections*/
      int ns;/*socket connected to client*/
      int namelen;/*length of client name*/
      int pktlen;/*length of packet received or sended*/
      if ((s = socket(AF-INET,SOCK-STREAM, 0))<0) {
      perror("Socket()");
      return;
      }
      /*Bind the socket to the server address.*/
      bzero((char*)&server, sizeof(server));
      server.sin-len =sizeof(struct sockaddr-in);
      server.sin-family=AF-INET;
      server.sin-port =htons(USERPORT);
      server.sin-addr.s-addr=INADDR-ANY;
      if (bind(s, (struct sockaddr *)&server, sizeof(server)) <0) {
      perror ("Bind()");
      return;
      }
      /*Listen for connections. Specify the backlog as 1. */
      if (listen(s,1)!=0) {
      perror("Listen()");
      return;
      }
      /*Accept a connection.*/
      namelen=sizeof(client);
      if ((ns = accept(s, (struct sockaddr *)&client,&namelen))==-1) {
      perror("Accept()");
      return;
      }
      /*Receive the message on the newly connected socket.*/
      for (;;){
      if ((pktlen = recv(ns, buf, 1024, 0))<0) {
      perror("Recv()");
      break;
      }
      else if (pktlen==0) {
      printf("Recv():return FAILED,connection is shut down! ");
      break;
      }
      else printf("Recv():return SUCCESS, packet length = %d ",pktlen);
      sleep(1); /*Sleep() 1秒鐘是為了減慢數據交換速度*/
      /*Send the message back to the client.*/
      if (send(ns, buf, pktlen, 0) <0) {
      perror("Send ()");
      break;
      }
      else printf("Send():return SUCCESS, packet length = %d ",pktlen);
      }
      close(ns);
      close(s);
      printf("Server ended successfully");
      }
      四、結束語
      本文試圖通過一個實例來說明如何使用WINSOCK實現Windows下網絡實時通信。從上面的討論可以看出,使用WINSOCK編制Windows下網絡軟件是比較方便的,WINSOCK提供的異步選擇機制使Socket強大的網絡編程功能能夠在Windows下得到應用。相信隨著INTERNET的推廣,TCP/IP網絡協議的廣泛使用,使用WINSOCK編制Windows網絡實時通信軟件將會有一個大的發展。

      參考文獻
      1 Martin Hall等.Windows Sockets-An Open Interface for Network Programm ing under Microsoft Windows.WINSOCK Document, 1993(6).2 孫義等.UNIX環境下的網絡程序設計.北京:希望公司,1991.3 梁振軍等.新編TCP/IP協議與計算機網絡互聯技術.北京:希望公司,1992.


      【C語言實的串行通信接口程序】相關文章:

      C語言實現串行通信接口程序08-06

      異步串行通信接口的IP核設計08-06

      ADμC812的串行外設接口(SPI)及其應用08-06

      一種用于單片機的紅外串行通信接口08-06

      一種多協議串行通信接口的設計方法08-06

      串行通信控制器85C30及其應用08-06

      基于Z85C30的多協議串行通信設計08-06

      c語言實習心得09-03

      AT93C46/56/55串行EEPROM及單片機程序08-06

      主站蜘蛛池模板: 亚洲欧洲av人一区二区| 国产精品亚洲а∨天堂2021 | 成人无码一区二区三区网站| 久久精品国产亚洲av高| 久久不见久久见免费视频| 国产永久免费高清在线| 欧美老人巨大XXXX做受视频| 最新精品露脸国产在线| 亚洲国产精品久久无人区| 国产综合有码无码中文字幕 | 亚洲av无码成人精品区一区| 亚洲ΑV久久久噜噜噜噜噜| 绝顶丰满少妇av无码| 亚洲美免无码中文字幕在线 | 美女一区二区三区亚洲麻豆| 偷拍精品一区二区三区| 欧美做受视频播放| 风骚少妇久久精品在线观看| 综合偷自拍亚洲乱中文字幕| 国产成人亚洲无码淙合青草| 91精品国产综合蜜臀蜜臀| 精品人妻日韩中文字幕| 亚洲黄色性视频| 国产一区国产二区在线视频| 在国产线视频A在线视频| 国内在线视频一区二区三区| 精品国产迷系列在线观看| 99久久精品国产一区二区暴力| 亚洲永久精品日韩成人av| 亚洲卡1卡2卡新区网站| 天堂在线最新版在线天堂| 福利视频在线一区二区| 亚洲日韩AV秘 无码一区二区 | 国产一区二区三区麻豆视频| 成人亚欧欧美激情在线观看| 亚洲日韩亚洲另类激情文学| 黑人大荫道bbwbbb高潮潮喷| 精品无码久久久久成人漫画| 国产真人无遮挡免费视频| 麻豆亚洲精品一区二区| 亚洲欧美日本久久网站|