Linux網路編程和通訊端__Arduino

來源:互聯網
上載者:User
1、通訊端概述

通訊端的本意是插座,在網路中用來描述電腦中不同程式與其他電腦程式的通訊方式。
常用的通訊端類型有3種:
1)流通訊端(SOCK——STREAM):使用了連線導向的可靠的資料通訊方式,即TCP通訊端
2)資料通訊端(Raw Sockets):使用了不連線導向的資料轉送方式,即UDP通訊端
3)原始通訊端(SOCK——RAW):沒有經過處理的IP資料包,可以根據自己程式的要求進行封裝。 2、常用函數

1、建立通訊端函數:成功時返迴文件描述符,失敗時返回-1

int socket(int domain,int type,int protocol);//參數domain用於指定建立通訊端所使用的協議族(可取AF_UNIX,AF_INET,AF_INTE6)//參數type指定通訊端的類型(可取SOCK_STREAM,SOCK_DGRAM,SOCK_RAW)//參數protocol通常設定為0

2、在指定通訊端上建立連結函數:成功時返回0,失敗時返回-1

int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);//參數sockfd是一個由函數socket建立的通訊端//參數serv_addr是一個地址結構,指定伺服器的IP地址和連接埠號碼//參數addrlen為參數serv_addr的長度

3、將一個通訊端和某個連接埠綁定在一起的函數:成功時返回0,失敗時返回-1

int bind(int sockfd,struct sockaddr *my_addr,socklen_t addrlen);//一般只有伺服器端的程式調用,參數my_addr指定了sockfd將綁定到的本地//地址,可以將參數my_addr的sin_addr設定為INADDR_ANY而不是某個確定//IP地址就可以綁定到任何網路介面。

4、把通訊端轉化為被動監聽函數:成功時返回0,失敗時返回-1

int listen(int s,int backlog);//參數s為通訊端,參數backlog指定連結請求隊列的最大長度;

5、接收串連請求函數:成功時返迴文件描述符,失敗時返回-1

int accept(int s,struct sockaddr *addr,socklen_t *addrlen);//參數s是由函數socket建立,經函數bind綁定到本地某一連接埠上,然後通過//函數listen轉化而來的監聽通訊端//參數addr用來儲存發起串連請求的主機的地址和連接埠//參數addrlen是addr所指向的結構體的大小

6、在TCP通訊端上發送資料函數:有串連

包含3要素:通訊端s,待發資料msg,資料長度len

ssize_t send(int s,const void *msg,size_t len,int flags);//函數只能對處於串連狀態的通訊端使用,參數s為已建立好串連的通訊端描述//符,即accept函數的傳回值//參數msg指向存放待發送資料的緩衝區//參數len為待發送資料的長度,參數flags為控制選項,一般設定為0

7、在TCP通訊端上接收資料函數:有串連

包含3要素:通訊端s,接收緩衝區buf,長度len

ssize_t recv(int s,void *buf,size_t len,int flags);//函數recv從參數s所指定的通訊端描述符(必須是連線導向的通訊端)上接收//資料並儲存到參數buf所指定的緩衝區//參數len則為緩衝區長度,參數flags為控制選項,一般設定為0

8、在UCP通訊端上發送資料函數:無串連

ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);//函數功能與函數send類似,但函數sendto不需要通訊端處於串連狀態,所以//該函數通常用來發送UDP資料,同時因為是不需連線的通訊端,在使用sendto時//需要指定資料的目的地址,參數msg指向待發送資料的緩衝區。//參數len指定了待發送資料的長度//參數flags是控制選項,含義與send函數中的一致//參數to用於指定目的地址,目的地址的長度由tolen指定

9、在UDP通訊端上接收資料函數:無串連

ssize_t recvfrom(int s ,void *buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen);//與函數recv功能類似,只是函數recv只能用於連線導向的通訊端,而函數//recvfrom沒有此限制,可以用於從不需連線的通訊端上接收資料//參數buf指向接收緩衝區//參數len指定了緩衝區的大小//參數flags是控制選項,含義與recv中的一致//如果參數from非空,且該通訊端不是連線導向的,則函數recvfrom返回時,//參數from中將儲存資料的源地址//參數fromlen在調用recvfrom前為參數from的長度,調用recvfrom後將//儲存from的實際大小

10、關閉通訊端函數:

int close(int fd);//參數fd為一個通訊端描述符;

11、多工函數:

int select(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);//參數n是需要監視的檔案描述符數//參數readfds指定需要監視的可讀檔案描述符集合//參數writefds指定需要監視的可寫檔案描述符集合//參數exceptfds指定需要監視的異常檔案描述符的集合//參數timeout指定了阻塞的時間
3、伺服器端通訊端(接收串連請求的通訊端)建立過程

第一步:調用socket函數建立通訊端。
第二步:調用bind函數分配IP地址和連接埠號碼。
第三部:調用listen函數轉為可接收請求狀態。
第四步:調用accept函數受理串連請求。

另外還有read/write,以及close。 4、用戶端通訊端(發送串連請求的通訊端)建立過程

只有兩步:
1、調用socket函數建立通訊端。
2、調用connect函數向伺服器端發送串連請求。

另外還有read/write,以及close。 5、Linux的檔案操作

檔案描述符:是系統自動分配給檔案或通訊端的整數。

每當組建檔案或通訊端,作業系統就會自動返回給我們一個整數。這個整數就是檔案描述符,即建立的檔案或通訊端的別名,方便稱呼而已。檔案描述符在Windows中又稱為控制代碼。

1、開啟檔案:

2、關閉檔案或通訊端:

3、將資料寫入檔案:

4、讀取檔案中的資料:

註:ssize_t = signed int, size_t = unsigned int,都是通過typedef聲明,為基礎資料型別 (Elementary Data Type)取的別名。既然已經有了基礎資料型別 (Elementary Data Type),那麼為什麼還需要為它取別名呢。是因為目前普遍認為int是32位的,而過去16位作業系統時代,int是16位的。根據系統的不同,時代的變化,基礎資料型別 (Elementary Data Type)的表現形式也隨著變化的如果為基礎資料型別 (Elementary Data Type)取了別名,以後要修改,也就只需要修改typedef聲明即可,這將大大減少代碼變動。 6、伺服器端執行個體

伺服器端受理串連請求的程式。編譯並運行該程式,建立等待串連請求的伺服器端。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>void error_handling(char *message);int main(int argc, const char * argv[]) {    int serv_sock;    int clnt_sock;    struct sockaddr_in serv_addr;    struct sockaddr_in clnt_addr;    socklen_t clnt_addr_size;    char message[] = "Hello World!";    if(argc != 2)    {        printf("Usage:%s <port>\n", argv[0]);        exit(1);    }    //(1)調用socket函數建立通訊端    serv_sock = socket(PF_INET, SOCK_STREAM, 0);    if(serv_sock == -1)        error_handling("socket() error");    memset(&serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);    serv_addr.sin_port = htons(atoi(argv[1]));    //(2)調用bind函數分配IP地址和連接埠號碼    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)        error_handling("bind() error");    //(3)調用listen函數轉為可接收請求狀態    if(listen(serv_sock, 5) == -1)        error_handling("listen() error");    clnt_addr_size = sizeof(clnt_addr);    //(4)調用accept函數受理串連請求.沒有串連請求時調用不會返回,直到有請求    clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size);    if(clnt_sock == -1)        error_handling("accept() error");    //(5)write函數用於傳輸資料。執行到此行說明已有了串連請求    //向檔案描述符為clnt_sock的用戶端檔案中傳輸message中的資料    write(clnt_sock, message, sizeof(message));    close(clnt_sock);//(6)    close(serv_sock);//(7)    return 0;}void error_handling(char *message){    fputs(message, stderr);    fputc('\n', stderr);    exit(1);}
7、用戶端執行個體
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>void error_handling(char *message);int main(int argc, const char * argv[]){    int sock;    struct sockaddr_in serv_addr;    char message[30];    int str_len;    if(argc != 3)    {        printf("Usage: %s <IP> <port>\n", argv[0]);        exit(1);    }    //(1)建立通訊端.但此時並不馬上分為用戶端或伺服器端    sock = socket(PF_INET, SOCK_STREAM, 0);    if(sock == -1)        error_handling("socket() error");    memset(&serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);    serv_addr.sin_port = htons(atoi(argv[2]));    //(2)調用connect函數向伺服器端發送串連請求.此時確定為用戶端    if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)        error_handling("connect() error");    //(3)調用read函數向自身聲明的message數組中儲存資料    str_len = read(sock, message, sizeof(message) - 1);    if(str_len == -1)        error_handling("read() error");    printf("Message from server: %s \n", message);    close(sock);//(4)    return 0;}void error_handling(char *message){    fputs(message, stderr);    fputc('\n', stderr);    exit(1);}
7、基本客戶/伺服器通訊端圖形展示

參考:《TCP/IP網路編程》及《Unix網路編程卷1》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.