天天看點

Socket通信

SocketServer:

SocketClient:

參考:

OSI中的層

功能

TCP/IP協定族

應用層

檔案傳輸,電子郵件,檔案服務,虛拟終端

TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

表示層

翻譯、加密、壓縮

沒有協定

會話層

對話控制、建立同步點(續傳)

傳輸層

端口尋址、分段重組、流量、差錯控制

TCP,UDP

網絡層

邏輯尋址、路由選擇

IP,ICMP,OSPF,EIGRP,IGMP,RIP,ARP,RARP

資料鍊路層

成幀、實體尋址、流量,差錯,接入控制

SLIP,CSLIP,PPP,MTU

實體層

設定網絡拓撲結構、比特傳輸、位同步

ISO2110,IEEE802,IEEE802.2

一、基本socket函數

Linux系統是通過提供套接字(socket)來進行網絡程式設計的。網絡的socket資料傳輸是一種特殊的I/O,socket也是一種檔案描述符。socket也有一個類似于打

開檔案的函數:socket(),調用socket(),該函數傳回一個整型的socket的描述符,随後的連接配接建立、資料傳輸等操作也都是通過該socket實作。

1、socket函數

syntax:

   int socket(int domain, int type, int protocol);

功能說明:

   調用成功,傳回socket檔案描述符;失敗,傳回-1,并設定errno

參數說明:

domain指明所使用的協定族,通常為PF_INET,表示TCP/IP協定;

type參數指定socket的類型,基本上有三種:資料流套接字、資料報套接字、原始套接字

protocol通常指派"0"。

  兩個網絡程式之間的一個網絡連接配接包括五種資訊:通信協定、本地協定位址、本地主機端口、遠端主機位址和遠端協定端口。socket資料結構中包含這五種資訊。

2、bind函數

syntax:  

   int bind(int sock_fd,struct sockaddr_in *my_addr, intaddrlen);

   将套接字和指定的端口相連。成功傳回0,否則,傳回-1,并置errno.

    sock_fd是調用socket函數傳回值,

my_addr是一個指向包含有本機IP位址及端口号等資訊的sockaddr類型的指針;

structsockaddr_in結構類型是用來儲存socket資訊的:

structsockaddr_in {

shortint sin_family;

unsignedshort int sin_port;

structin_addr sin_addr;

unsignedchar sin_zero[8];

};

    addrlen為sockaddr的長度。

3、connect函數

    int connect(int sock_fd, struct sockaddr *serv_addr,intaddrlen);

   用戶端發送服務請求。成功傳回0,否則傳回-1,并置errno。

   sock_fd 是socket函數傳回的socket描述符;serv_addr是包含遠端主機IP位址和端口号的指針;addrlen是結構sockaddr_in的長度。

4、listen函數

   int listen(int sock_fd, int backlog);

   等待指定的端口的出現用戶端連接配接。調用成功傳回0,否則,傳回-1,并置errno.

   sock_fd 是socket()函數傳回值;

   backlog指定在請求隊列中允許的最大請求數

5、accecpt函數

   int accept(int sock_fd, struct sockadd_in* addr, intaddrlen);

   用于接受用戶端的服務請求,成功傳回新的套接字描述符,失敗傳回-1,并置errno。

   sock_fd是被監聽的socket描述符,

   addr通常是一個指向sockaddr_in變量的指針,

   addrlen是結構sockaddr_in的長度。

6、write函數

    ssize_t write(int fd,const void *buf,size_t nbytes)

    write函數将buf中的nbytes位元組内容寫入檔案描述符fd.成功時傳回寫的位元組數.失敗時傳回-1. 并設定errno變量.

    在網絡程式中,當我們向套接字檔案描述符寫時有倆種可能:

      1)write的傳回值大于0,表示寫了部分或者是全部的資料.

      2)傳回的值小于0,此時出現了錯誤.需要根據錯誤類型來處理.

        如果錯誤為EINTR表示在寫的時候出現了中斷錯誤.

        如果錯誤為EPIPE表示網絡連接配接出現了問題.

7、read函數

    ssize_t read(int fd,void *buf,size_t nbyte)

函數說明:

    read函數是負責從fd中讀取内容.當讀成功時,read傳回實際所讀的位元組數,如果傳回的值是0 表示已經讀到檔案的結束了,小于0表示出現了錯誤.

    如果錯誤為EINTR說明讀是由中斷引起的,

    如果錯誤是ECONNREST表示網絡連接配接出了問題.

8、close函數

int close(sock_fd);

說明:

當所有的資料操作結束以後,你可以調用close()函數來釋放該socket,進而停止在該socket上的任何資料操作:

函數運作成功傳回0,否則傳回-1

二、socket程式設計的其他函數說明

1、網絡位元組順序及其轉換函數

1)網絡位元組順序

每一台機器内部對變量的位元組存儲順序不同,而網絡傳輸的資料是一定要統一順序的。是以對内部位元組表示順序與網絡位元組順序不同的機器,

一定要對資料進行轉換,從程式的可移植性要求來講,就算本機的内部位元組表示順序與網絡位元組順序相同也應該在傳輸資料以前先調用資料轉換函數,

以便程式移植到其它機器上後能正确執行。真正轉換還是不轉換是由系統函數自己來決定的。

2)有關的轉換函數

* unsigned short int htons(unsigned short int hostshort):

主機位元組順序轉換成網絡位元組順序,對無符号短型進行操作4bytes

* unsigned long int htonl(unsigned long int hostlong):

主機位元組順序轉換成網絡位元組順序,對無符号長型進行操作8bytes

* unsigned short int ntohs(unsigned short int netshort):

網絡位元組順序轉換成主機位元組順序,對無符号短型進行操作4bytes

* unsigned long int ntohl(unsigned long int netlong):

網絡位元組順序轉換成主機位元組順序,對無符号長型進行操作8bytes

注:以上函數原型定義在netinet/in.h裡

2、IP位址轉換

有三個函數将數字點形式表示的字元串IP位址與32位網絡位元組順序的二進制形式的IP位址進行轉換

(1) unsigned long intinet_addr(const char * cp):該函數把一個用數字和點表示的IP位址的字元串轉換成一個無符号長整型,如:struct sockaddr_in ina

ina.sin_addr.s_addr=inet_addr("202.206.17.101")

該函數成功時:傳回轉換結果;失敗時傳回常量INADDR_NONE,該常量=-1,二進制的無符号整數-1相當于255.255.255.255,這是一個廣播位址,是以在程式中調用iner_addr()時,一定要人為地對調用失敗進行處理。由于該函數不能處理廣播位址,是以在程式中應該使用函數inet_aton()。

(2)int inet_aton(const char * cp,structin_addr * inp):此函數将字元串形式的IP位址轉換成二進制形式的IP位址;成功時傳回1,否則傳回0,轉換後的IP位址存儲在參數inp中。

(3) char * inet_ntoa(struct in-addr in):将32位二進制形式的IP位址轉換為數字點形式的IP位址,結果在函數傳回值中傳回,傳回的是一個指向字元串的指針。

3、位元組處理函數

Socket位址是多位元組資料,不是以空字元結尾的,這和C語言中的字元串是不同的。Linux提供了兩組函數來處理多位元組資料,一組以b(byte)開頭,是和BSD系統相容的函數,另一組以mem(記憶體)開頭,是ANSI C提供的函數。

以b開頭的函數有:

(1) void bzero(void * s,int n):将參數s指定的記憶體的前n個位元組設定為0,通常它用來将套接字位址清0。

(2) void bcopy(const void * src,void * dest,int n):從參數src指定的記憶體區域拷貝指定數目的位元組内容到參數dest指定的記憶體區域。

(3) int bcmp(const void * s1,const void * s2,int n):比較參數s1指定的記憶體區域和參數s2指定的記憶體區域的前n個位元組内容,如果相同則傳回0,否則傳回非0。

注:以上函數的原型定義在strings.h中。

以mem開頭的函數有:

(1) void * memset(void * s,int c,size_t n):将參數s指定的記憶體區域的前n個位元組設定為參數c的内容。

(2) void * memcpy(void * dest,const void * src,size_t n):功能同bcopy(),差別:函數bcopy()能處理參數src和參數dest所指定的區域有重疊的情況,memcpy()則不能。

(4) int memcmp(const void * s1,const void * s2,size_t n):比較參數s1和參數s2指定區域的前n個位元組内容,如果相同則傳回0,否則傳回非0。

注:以上函數的原型定義在string.h中。

本文轉自蓬萊仙羽51CTO部落格,原文連結:http://blog.51cto.com/dingxiaowei/1366484,如需轉載請自行聯系原作者

繼續閱讀