1. 程式人生 > >對於socket網路程式設計,搗鼓了一週多,終於實現了電腦為服務端,學習板為客戶端之間的通訊

對於socket網路程式設計,搗鼓了一週多,終於實現了電腦為服務端,學習板為客戶端之間的通訊

最開始是網上找到相關的客戶端,和服務端 的程式,然後試著去理解,但是這個過程很難過,因為從來沒有接觸過的,但是沒辦法,只能硬著頭皮啃,問老師,問學長,網上看視訊。終於是吧他啃下來了。

服務端的程式碼:

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <fcntl.h> #include <sys/poll.h> #include <sys/epoll.h> #define BACKLOG 100     int main()   {     int iListenSock = socket(AF_INET, SOCK_STREAM, 0); //int socket(int domain, int type, int protocol);socket函式對應於普通檔案的開啟操作。普通檔案的開啟操作返回一個檔案描述字,而socket()用於建立一個socket描述符(socket descriptor),它唯一標識一個socket。這個socket描述字跟檔案描述字一樣,後續的操作都有用到它,把它作為引數,通過它來進行一些讀寫操作。 //1.協議族決定了socket的地址型別,在通訊中必須採用對應的地址,如AF_INET決定了要用ipv4地址(32位的)與埠號(16位的)的組合、AF_UNIX決定了要用一個絕對路徑名作為地址。 //2.type:指定socket型別。常用的socket型別有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等 //3.protocol故名思意,就是指定協議。常用的協議有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它們分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議     sockaddr_in addr;//     memset(&addr, 0, sizeof(addr));     inet_aton("192.168.1.66", &addr.sin_addr); //是一個改進的方法來將一個字串IP地址轉換為一個32位的網路序列IP地址。 /*     struct sockaddr_in                {  unsigned short int sin_family;//協議族(family)連線方式                       uint16_t sin_port;//定義埠號,可以直接指定,也可由系統指定,也是網路位元組序,                                  一般用htons()函式轉換。                       struct in_addr sin_addr;//為ip地址,是二進位制的網路位元組序,                                            一般用inet_addr()函式完成轉換                       unsigned char sin_zero[8];//一般不使用      }     */     addr.sin_family = AF_INET;//協議族(family)採用IPv4網路協議     addr.sin_port = htons(8888);//伺服器監聽埠號 8888        int iOpt = 1;     setsockopt(iListenSock, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt)); // 標配     bind(iListenSock, (sockaddr*)&addr, sizeof(addr));//bind()函式把一個地址族中的特定地址賦給socket。例如對應AF_INET、AF_INET6就是把一個ipv4或ipv6地址和埠號組合賦給socket。     listen(iListenSock, BACKLOG);//BACKLOG 100指定同時能夠處理的最大連線要求      epoll_event ev;     ev.data.fd = iListenSock;     ev.events = EPOLLIN;          epoll_event events[BACKLOG + 1];       int epollFD = epoll_create(BACKLOG + 1);   // 告訴核心監測的數目, 返回的epollFD為epoll管理控制代碼     epoll_ctl(epollFD, EPOLL_CTL_ADD, iListenSock, &ev);  // 將ev和對應的iListenSock新增到epoll控制代碼,用於被epollFD管理     while(1)      {         int timeoutMS = -1; // 永不超時         int nfds = epoll_wait(epollFD, events, BACKLOG + 1, timeoutMS);   // events和nfds是一對輸出值         printf("nfds is %d\n", nfds);                  for(int i = 0; i < nfds; i++)          {               if(events[i].data.fd == iListenSock)         // 用於監聽客戶端連線的socket             {                   int iConnSock = accept(iListenSock, NULL, NULL);                 if (iConnSock < 0)                   {                     continue;                 }                   ev.data.fd = iConnSock;                 ev.events = EPOLLIN;                 epoll_ctl(epollFD, EPOLL_CTL_ADD, iConnSock, &ev);  // 將ev和對應的iConnSock新增到epoll控制代碼,用於被epollFD管理                   printf("new sock came, fd is %d\n", iConnSock);             }              else              {                 int iConnSock = events[i].data.fd;      // 用於通訊的socket                 char szBuf[1024] = {0};                 int recvLen = recv(iConnSock, szBuf, sizeof(szBuf) - 1, 0);                 if (recvLen > 0)                  {                       printf("recv data [%s] from fd [%d]\n", szBuf, iConnSock);                 }                 else if(0 == recvLen)                 {                       ev.data.fd = iConnSock;                     epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev);                     close(iConnSock);                     printf("connection closed, local fd is [%d]\n", iConnSock);                 }                 else                 {                     ev.data.fd = iConnSock;                     epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev);                     close(iConnSock);                     printf("recv error, local fd is [%d]\n", iConnSock);                 }             }           }       }            close(epollFD);     close(iListenSock);     return 0; }  

雖然程式搞懂了,但是對於網路配置的,還是不懂,在其中遇到,PC,虛擬機器,板子的網路Ping通

主要問題如下

這個是因為程式裡面的IP地址不是你伺服器的地址,導致雖然在虛擬機器和板子網路可以ping得通,但是執行客戶端的程式沒有反應。解決方法,通過在虛擬機器輸入ifconfig 檢視IP地址。

接下來可能會出現接來的問題;

你發現你的Ip地址好像沒有,

這可能是你要去開啟你的網絡卡設定。

按照步驟走,IP可以自己選擇,也可以選擇自動,但是還是自己輸入比較好,因為要選擇跟板子上通一個網段。

我通過交叉編譯得到了板子上linux可執行程式,許多方便改變,這個也是一個大問題,我嘗試了很久通過NFS但是就是設定不好服務端的檔案。最後還是選擇了用u盤掛載,