3.解決方案
3.1 建立Socket
為了建立建立S o c k e t,程序可以調(diào)用socket函數(shù),該函數(shù)返回一個(gè)類似于文件描述符的句柄。socket函數(shù)原型為:
int socket(int domain, int type,intprotocol);
domain指明所使用的協(xié)議族,通常為PF_INET,表示互聯(lián)網(wǎng)協(xié)議族(TCP/IP協(xié)議族);type參數(shù)指定socket的類型:SOCK_STREAM或SOCK_DGRAM,Socket接口還定義了原始 Socket(SOCK_RAW),允許程序使用低層協(xié)議;protocol通常賦值“0”.Socket()調(diào)用返回一個(gè)整型socket描述符,你可以在后面的調(diào)用使用它。
Socket描述符是一個(gè)指向內(nèi)部數(shù)據(jù)結(jié)構(gòu)的指針,它指向描述符表入口。調(diào)用Socket函數(shù)時(shí),socket執(zhí)行體將建立一個(gè)Socket,實(shí)際上“建立一個(gè)Socket”意味著為一個(gè)Socket數(shù)據(jù)結(jié)構(gòu)分配存儲(chǔ)空間。Socket執(zhí)行體為你管理描述符表。
兩個(gè)網(wǎng)絡(luò)程序之間的一個(gè)網(wǎng)絡(luò)連接包括五種信息:通信協(xié)議、本地協(xié)議地址、本地主機(jī)端口、遠(yuǎn)端主機(jī)地址和遠(yuǎn)端協(xié)議端口。Socket數(shù)據(jù)結(jié)構(gòu)中包含這五種信息。
3.2 配置Socket
通過(guò)socket調(diào)用返回一個(gè)socket描述符后,在使用socket進(jìn)行網(wǎng)絡(luò)傳輸以前,必須配置該socket.面向連接的socket客戶端通過(guò)調(diào)用Connect函數(shù)在socket數(shù)據(jù)結(jié)構(gòu)中保存本地和遠(yuǎn)端信息。無(wú)連接socket的客戶端和服務(wù)端以及面向連接socket的服務(wù)端通過(guò)調(diào)用bind函數(shù)來(lái)配置本地信息。
Bind函數(shù)將socket與本機(jī)上的一個(gè)端口相關(guān)聯(lián),隨后你就可以在該端口監(jiān)聽(tīng)服務(wù)請(qǐng)求。
Bind函數(shù)原型為:
int bind(int sockfd,struct sockaddr*my_addr,int addrlen);
Sockfd是調(diào)用socket函數(shù)返回的socket描述符,my_addr是一個(gè)指向包含有本機(jī)IP地址及端口號(hào)等信息的sockaddr類型的指針;addrlen常被設(shè)置為3.3 建立連接
面向連接的客戶程序使用Connect函數(shù)來(lái)配置socket并與遠(yuǎn)端服務(wù)器建立一個(gè)TCP連接,其函數(shù)原型為:
int connect(int sockfd,struct sockaddr*serv_addr,int addrlen);
Sockfd是socket函數(shù)返回的socket描述符;serv_addr是包含遠(yuǎn)端主機(jī)IP地址和端口號(hào)的指針;addrlen是遠(yuǎn)端地址結(jié)構(gòu)的長(zhǎng)度。
Connect函數(shù)在出現(xiàn)錯(cuò)誤時(shí)返回-1,并且設(shè)置errno為相應(yīng)的錯(cuò)誤碼。進(jìn)行客戶端程序設(shè)計(jì)無(wú)須調(diào)用bind(),因?yàn)檫@種情況下只需知道目的機(jī)器的IP地址,而客戶通過(guò)哪個(gè)端口與服務(wù)器建立連接并不需要關(guān)心,socket執(zhí)行體為你的程序自動(dòng)選擇一個(gè)未被占用的端口,并通知你的程序數(shù)據(jù)什么時(shí)候到達(dá)端口。
Connect函數(shù)啟動(dòng)和遠(yuǎn)端主機(jī)的直接連接。只有面向連接的客戶程序使用socket時(shí)才需要將此socket與遠(yuǎn)端主機(jī)相連。無(wú)連接協(xié)議從不建立直接連接。面向連接的服務(wù)器也從不啟動(dòng)一個(gè)連接,它只是被動(dòng)的在協(xié)議端口監(jiān)聽(tīng)客戶的請(qǐng)求。
Listen函數(shù)使socket處于被動(dòng)的監(jiān)聽(tīng)模式,并為該socket建立一個(gè)輸入數(shù)據(jù)隊(duì)列,將到達(dá)的服務(wù)請(qǐng)求保存在此隊(duì)列中,直到程序處理它們。
int listen(int sockfd,int backlog);
首先,當(dāng)accept函數(shù)監(jiān)視的socket收到連接請(qǐng)求時(shí),socket執(zhí)行體將建立一個(gè)新的 socket,執(zhí)行體將這個(gè)新socket和請(qǐng)求連接進(jìn)程的地址聯(lián)系起來(lái),收到服務(wù)請(qǐng)求的初始socket仍可以繼續(xù)在以前的socket上監(jiān)聽(tīng),同時(shí)可以在新的socket描述符上進(jìn)行數(shù)據(jù)傳輸操作。
3.4 傳輸數(shù)據(jù)
Send()和recv()這兩個(gè)函數(shù)用于面向連接的socket上進(jìn)行數(shù)據(jù)傳輸。
Sockfd是你用來(lái)傳輸數(shù)據(jù)的socket描述符;msg是一個(gè)指向要發(fā)送數(shù)據(jù)的指針;Len是以字節(jié)為單位數(shù)據(jù)的長(zhǎng)度;flags一般情況下設(shè)置為0(關(guān)于該參數(shù)的用法可參照man手冊(cè))。
Send()函數(shù)返回實(shí)際上發(fā)送出的字節(jié)數(shù),可能會(huì)少于你希望發(fā)送的數(shù)據(jù)。在程序中應(yīng)該將send()的返回值與欲發(fā)送的字節(jié)數(shù)進(jìn)行比較。當(dāng)send()返回值與len不匹配時(shí),應(yīng)該對(duì)這種情況進(jìn)行處理。
3.5 傳輸結(jié)束
當(dāng)所有的數(shù)據(jù)操作結(jié)束以后,你可以調(diào)用close()函數(shù)來(lái)釋放該socket,從而停止在該socket上的任何數(shù)據(jù)操作。
評(píng)論