C語言之socket開發(fā)TCPUDP通信總結(jié)_第1頁
C語言之socket開發(fā)TCPUDP通信總結(jié)_第2頁
C語言之socket開發(fā)TCPUDP通信總結(jié)_第3頁
C語言之socket開發(fā)TCPUDP通信總結(jié)_第4頁
C語言之socket開發(fā)TCPUDP通信總結(jié)_第5頁
已閱讀5頁,還剩19頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、、什么是 socket ?Socket的英文原義是“孔”或“插座”。 在編程中,Socket被稱做 套 接字,是網(wǎng)絡(luò)通信中的一種約定。 Socket編程的應(yīng)用無處不在, 都與Socket 編程有關(guān)。我們平時(shí)使用瀏覽器查資料, 這個(gè)過程的技術(shù)原理是怎樣的呢?服務(wù)器(服務(wù)端)服務(wù)端返回?cái)?shù)據(jù)客戶端發(fā)起請求瀏覽器(客戶端)呈現(xiàn)文字、圖片等數(shù)據(jù)給用戶用戶輸入網(wǎng)址、問題用戶我們平時(shí)使用瀏覽器,大致就是這樣的一個(gè)過程。這里有兩個(gè)重要的名 詞:服務(wù)端與客戶端。Socket編程的目的就是如何實(shí)現(xiàn)這兩端之間的通信 1、Socket編程在嵌入式中也很重要Socket編程不僅僅在互聯(lián)網(wǎng)方面很重要,在我們的嵌入式方面也

2、是非常的重要,因?yàn)楝F(xiàn)在很多電子設(shè)備都趨向于聯(lián)網(wǎng)。比如很多嵌入式工作的招聘要求都會(huì)有這一條要求:二、Socket編程中的幾個(gè)重要概念Socket編程用于解決我們客戶端與服務(wù)端之間通信的問題。我們平時(shí)多多少少都有聽過IP地址、端口、TCP協(xié)議、UDPB議等概念,這些都與Socket編程中相關(guān),想要知道怎么用起來,當(dāng)然得先了解它們的一些介 紹。下面看一下這些專業(yè)術(shù)語的一些要點(diǎn)介紹:1、什么是IP地址?IP地址(InternetProtocolAddress)是指互聯(lián)網(wǎng)協(xié)議地址,又譯為 網(wǎng)際協(xié)議地址。IP地址被用來給Internet上的電腦一個(gè)編號(hào)。我們可以把“個(gè)人電腦”比作“一臺(tái)電話”,那么“IP地

3、址”就相當(dāng)于“電話號(hào)碼”。若計(jì)算機(jī)1知道計(jì)算機(jī)2的IP地址,則計(jì)算機(jī)1就能訪問計(jì)算機(jī) 2。IP地址是一個(gè)32位的二進(jìn)制數(shù),通常被分割為4個(gè)“8位二進(jìn)制數(shù)”(也就是4個(gè)字節(jié))。IP地址通常用點(diǎn)分十進(jìn)制表示成(a.b.c.d )的形式,其中,a,b,c,d 都是0255之間的十進(jìn)制整數(shù)。例:點(diǎn)分十進(jìn)IP地址(), 實(shí) 際上是 32 位二進(jìn)制 數(shù)(01100100.00000100.00000101.00000110)。IP地址有 IPv4與IPv6之分,現(xiàn)在用得較多的是IPv4。其中,有一個(gè)特殊的IP地址需要我們記?。? ,這是回送地址,即本地機(jī), 一般用來測試

4、使用。后邊我們的實(shí)例中會(huì)用到。關(guān)于IP地址還有很多知識(shí)要點(diǎn),但是對(duì)于在Socket編程中的應(yīng)用,我們暫且知道這么多就可以。2、什么是TCP/IP端口?上一點(diǎn)中我們提到,若計(jì)算機(jī)1知道計(jì)算機(jī)2的IP地址,則計(jì)算機(jī)1就能訪問計(jì)算機(jī) 2。但是,我們要訪問計(jì)算機(jī)2中的不同的應(yīng)用軟件,則還得需要一個(gè)信息:端口。端口使用16bit進(jìn)行編號(hào),即其范圍為: 065536但 01023 的端口一般由系統(tǒng)分配給特定的服務(wù)程序,例如 Web服務(wù)的 端口號(hào)為80 , FTP服務(wù)的端口號(hào)為 21等。3、什么是協(xié)議?協(xié)議(Protocol )是通信雙方進(jìn)行數(shù)據(jù)交互的一種約定。如 TCR UDP 協(xié)議:(1) TCP協(xié)議T

5、CP (Transmission Control Protocol傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,數(shù)據(jù)可以準(zhǔn)確發(fā)送,數(shù)據(jù)丟 失會(huì)重發(fā)。TCP協(xié)議常用于web應(yīng)用中。TCP連接(三次握手)TCP傳輸起始時(shí),客戶端、服務(wù)端要完成三次數(shù)據(jù)交互工作才能建立連接, 常稱為三次握手??尚蜗蟊扔鳛槿缦聦?duì)話:客戶端:服務(wù)端您好,我有數(shù)據(jù)要發(fā)給你,請求您開通訪問權(quán)限。服務(wù)端:客戶端您好,已給您開通權(quán)限,您可以發(fā)送數(shù)據(jù)了??蛻舳耍菏盏?,謝謝具體示意圖為:三次握手這里的SYN和ACK是都是標(biāo)志位,其中 SYN代表新建一個(gè)連接,ACK代表確 認(rèn)。其中m> n都是隨機(jī)數(shù)。具體說

6、明如:?第一次握手:SYNB志位被置位,客戶端向服務(wù)端發(fā)送一個(gè)隨機(jī)數(shù)m=?第二次握手:ACK SYN標(biāo)志位被置位。服務(wù)端向客戶端發(fā)送m+1表示確認(rèn)剛才收到的數(shù)據(jù),同時(shí)向客戶端發(fā)送一個(gè)隨機(jī)數(shù)n0?第三次握手:ACKfe志被置位??蛻舳讼蚍?wù)端發(fā)送 n+1表示確認(rèn)收到數(shù)據(jù)。TCP斷開(四次揮手)TCP斷開連接時(shí),客戶端、服務(wù)端要完成四次數(shù)據(jù)交互工作才能建立連接,常稱為四次揮手??尚蜗蟊扔鳛槿缦聦?duì)話:客戶端:服務(wù)端您好,我發(fā)送數(shù)據(jù)完畢了,即將和您斷開連接。服務(wù)端:客戶端您好,我稍稍準(zhǔn)備一下,再給您斷開服務(wù)端:客戶端您好,我準(zhǔn)備好了,您可以斷開連接了。客戶端:好的,合作愉快!具體示意圖為:四次揮手這里

7、的FIN也是一個(gè)標(biāo)志位,代表斷開連接。具體說明類似 三次握 手。為什么建立連接只需要三次數(shù)據(jù)交互,而斷開連接需要四次呢?建立連接時(shí),服務(wù)端在監(jiān)聽狀態(tài)下,收到建立連接請求的 SYN報(bào)文后,把ACK和SYN放在一個(gè)報(bào)文里發(fā)送給客戶端。而關(guān)閉連接時(shí),當(dāng)收到對(duì)方的FIN報(bào)文時(shí),僅僅表示對(duì)方不再發(fā)送數(shù)據(jù) 了但是還能接收數(shù)據(jù),己方也未必全部數(shù)據(jù)都發(fā)送給對(duì)方了,所以己方可以立即close ,也可以發(fā)送一些數(shù)據(jù)給對(duì)方后,再發(fā)送 FIN報(bào)文給對(duì)方來表示 同意現(xiàn)在關(guān)閉連接,因此,己方ACK和FIN 一般都會(huì)分開發(fā)送。(2) UDPB議UDP(User Datagram Protocol , 用戶數(shù)據(jù)報(bào)協(xié)議)是一種

8、無連接的 傳輸層協(xié)議,提供面向事務(wù)的簡單不可靠信息傳送服務(wù),可以保證通訊效 率,傳輸延時(shí)小。例如視頻聊天應(yīng)用中用的就是UDPB議,這樣可以保證及時(shí)丟失少量數(shù)據(jù),視頻的顯示也不受很大影響。4、什么是協(xié)議族?協(xié)議族是多個(gè)協(xié)議的統(tǒng)稱。比如我們的TCP/IP協(xié)議族,其不僅僅是TCP協(xié)議、IP協(xié)議,而是多個(gè)協(xié)議的集合,具包含 IP、TCR UDP FTP、 SMT琳協(xié)議。三、socket編程的 API接口1、Linux 下的 socket API 接口(1)創(chuàng)建 socket : socket()函數(shù)函數(shù)原型:1. int socket(int af, int type, int protocol);?

9、 af參數(shù):af為地址族(Address Family ),也就是IP 地址類型,常用的 有 AFINET 和 AFINET6 ,其前綴也可以是 PF( Protocol Family),即 PFINET和 PFINET6 o? type參數(shù):type 為數(shù)據(jù)傳輸方式,常用的有面向連接(SOCK_STREAM方式(即TCP) 和 無連接(SOCK_DGRAM勺方式(即 UDP 。? protocol 參數(shù): protocol 表示傳輸協(xié)議,常用的 有 IPPROTO_TCP和 IPPTOTO_UDP分另表示 TCP傳輸協(xié)議和 UDP傳 輸協(xié)議。使用示例:創(chuàng)建TCP套接字:1. int tcp_

10、socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);創(chuàng)建UDP套接字:1. int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);(2)綁定套接字:bind()函數(shù)函數(shù)原型:1. int bind(int sock, struct sockaddr *addr, socklen_t addrlen);? sock參數(shù):sock為socket 文件描述符。? addr參數(shù):addr為sockaddr 結(jié)構(gòu)體變量的指針。? addrlen 參數(shù):addrlen 為addr 變量的大小,可

11、由 sizeof() 計(jì)算得出。 使用示例:將創(chuàng)建的套接字 ServerSock與本地IP 、端口 1314進(jìn)行綁 定:1. /*創(chuàng)建服務(wù)端 socket */2. int ServerSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);3.4. /*設(shè)置服務(wù)端信息*/5. struct sockaddr_in ServerSockAddr;memset(&ServerSockAddr, 0, sizeof(ServerSockAddr);ServerSockAddr 清零ServerSockAddr.sin_famil

12、y = PF_INET;IPv4地址ServerSockAddr.sin_addr.s_addr = inet_addr("");ServerSockAddr.sin_port = htons(1314);/給結(jié)構(gòu)體/使用本機(jī)IP地址/端口./*綁定套接字*/.bind(ServerSock, (SOCKADDR*)&ServerSockAddr, sizeof(SOCKADDR);其中structsockaddr_in類型的結(jié)構(gòu)體變量用于保存IPv4的IP信息。若是IPv6,則有對(duì)應(yīng)的結(jié)構(gòu)體:struct sockaddr_in6 .sa_fam

13、ily_t sin6_family;in_port_t sin6_port;uint32_t sin6_flowinfo;struct in6_addr sin6_addr;uint32_t sin6_scope_id;/地址類型,取值為 AF_INET6/ 16位端口號(hào)/ IPv6流信息/具體的IPv6地址/接口范圍ID;(3)建立連接:connect。函數(shù)函數(shù)原型:1. int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);參數(shù)與 bind()的參數(shù)類似。使用示例:2. int ClientSock = s

14、ocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);3. connect(ClientSock, (SOCKADDR*)&ServerSockAddr, sizeof(SOCKADDR);(4)監(jiān)聽:listen() 函數(shù)函數(shù)原型:1. int listen(int sock, int backlog);? sock參數(shù):sock為需要進(jìn)入監(jiān)聽狀態(tài)的套接字。? backlog參數(shù):backlog 為請求隊(duì)列的最大長度使用示例:2. /*進(jìn)入監(jiān)聽狀態(tài)*/3. listen(ServerSock, 10);(5)接收請求:accept()函數(shù)函數(shù)原型:1. i

15、nt accept(int sock, struct sockaddr *addr, socklen_t *addrlen);? sock參數(shù):sock為服務(wù)器端套接字。? addr參數(shù):addr為sockaddr_in 結(jié)構(gòu)體變量。? addrlen 參數(shù):addrlen 為參數(shù)addr 的長度,可由 sizeof() 求得。?返回值:一個(gè)新的套接字,用于與客戶端通信。使用示例:1. /*監(jiān)聽客戶端請求,accept函數(shù)返回一個(gè)新的套接字,發(fā)送和接收都是 用這個(gè)套接字*/2. int ClientSock = accept(ServerSock, (SOCKADDR*)&Client

16、Addr, &len);(6)關(guān)閉:close()函數(shù)函數(shù)原型:1. int close(int fd);? fd :要關(guān)閉的文件描述符。使用示例:1. close(ServerSock);(7)數(shù)據(jù)的接收和發(fā)送數(shù)據(jù)收發(fā)函數(shù)有幾組:? read()/write()? recv()/send()? readv()/writev()? recvmsg()/sendmsg()? recvfrom()/sendto()函數(shù)原型:1. ssize_t read(int fd, void *buf, size_t count);2. ssize_t write(int fd, const void

17、 *buf, size_t count);3. ssize_t send(int sockfd, const void *buf, size_t len, int flags);4. ssize_t recv(int sockfd, void *buf, size_t len, int flags);5. ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,6. const struct sockaddr *dest_addr, socklen_taddrlen);7. ssize_t recvfrom(int s

18、ockfd, void *buf, size_t len, int flags,8. struct sockaddr *src_addr, socklen_t *addrlen);9. ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);10. ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);這里介紹一下 recv()/send() 、recvfrom()/sendto() 。recv()函數(shù):1. ssize_t recv(int sockfd,

19、 void *buf, size_t len, int flags);? sockfd參數(shù):sockfd 為要接收數(shù)據(jù)的套接字。? buf參數(shù):buf為要接收的數(shù)據(jù)的緩沖區(qū)地址。? len參數(shù):len為要接收的數(shù)據(jù)的字節(jié)數(shù)。? flags參數(shù):flags 為接收數(shù)據(jù)時(shí)的選項(xiàng),常設(shè)為 0osend()函數(shù):1. ssize_t send(int sockfd, const void *buf, size_t len, int flags);? sockfd參數(shù):sockfd為要發(fā)送數(shù)據(jù)的套接字。? buf參數(shù):buf為要發(fā)送的數(shù)據(jù)的緩沖區(qū)地址。? len參數(shù):len為要發(fā)送的數(shù)據(jù)的字節(jié)數(shù)。? f

20、lags參數(shù):flags 為發(fā)送數(shù)據(jù)時(shí)的選項(xiàng),常設(shè)為 0o recvfrom() 函數(shù):1. ssize_t recvfrom(int sock, void *buf, size_t nbytes, int flags, struct sockadr *from, socklen_t *addrlen);? sock:用于接收UDP數(shù)據(jù)的套接字;? buf:保存接收數(shù)據(jù)的緩沖區(qū)地址;? nbytes :可接收的最大字節(jié)數(shù)(不能超過buf緩沖區(qū)的大小);? flags :可選項(xiàng)參數(shù),若沒有可傳遞0;? from :存有發(fā)送端地址信息的sockaddr結(jié)構(gòu)體變量的地址;? addrlen :保存參

21、數(shù)from 的結(jié)構(gòu)體變量長度的變量地址值。sendto()函數(shù):1. ssize_t sendto(int sock, void *buf, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen);? sock :用于傳輸 UDP數(shù)據(jù)的套接字;? buf:保存待傳輸數(shù)據(jù)的緩沖區(qū)地址;? nbytes :帶傳輸數(shù)據(jù)的長度(以字節(jié)計(jì));? flags :可選項(xiàng)參數(shù),若沒有可傳遞0;? to :存有目標(biāo)地址信息的sockaddr結(jié)構(gòu)體變量的地址;? addrlen :傳遞給參數(shù)to 的地址值結(jié)構(gòu)體變量的長度。2、window

22、s 下的 socket API 接口跟Linux下的差不多:1. SOCKET socket(int af, int type, int protocol);2. int bind(SOCKET sock, const struct sockaddr *addr, int addrlen);3. int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen);4. int listen(SOCKET sock, int backlog);5. SOCKET accept(SOCKET sock, struct so

23、ckaddr *addr, int *addrlen);6. int closesocket( SOCKET s);7. int send(SOCKET sock, const char *buf, int len, int flags);8. int recv(SOCKET sock, char *buf, int len, int flags);9. int recvfrom(SOCKET sock, char *buf, int nbytes, int flags, const struct sockaddr *from, int *addrlen);10. int sendto(SOC

24、KET sock, const char *buf, int nbytes, int flags, const struct sockadr *to, int addrlen);3、TCR UDP!信的socket編程過程圖(1) TCP通信socket編程過程服務(wù)端(2) UDPWS socket 編程過程服務(wù)端四、socket的應(yīng)用實(shí)例1、基于TCP的本地客戶端、服務(wù)端信息交互實(shí)例本例的例子實(shí)現(xiàn)的功能為:本地TCP客戶端往本地 TCP服務(wù)端發(fā)送數(shù)據(jù),TCP客戶端。這個(gè)TCP服務(wù)端收到數(shù)據(jù)則會(huì)打印輸出,同時(shí)把原數(shù)據(jù)返回給例子類似于我們在做單片機(jī)的串口實(shí)驗(yàn)時(shí),用口上位機(jī)往我們的單片機(jī)發(fā) 送數(shù)據(jù)

25、,單片機(jī)收到數(shù)據(jù)則把該數(shù)據(jù)原樣返回給上位機(jī)。(1) windows 的程序:K 務(wù)端程序 tcp_server.c..9.10.#include <stdio.h>#include <winsock2.h>#defineBUFLEN 100int main(void) WSADATA wd;SOCKET ServerSock, ClientSock; char BufBUF_LEN = 0;11. SOCKADDR ClientAddr;12. SOCKADDR_IN ServerSockAddr;13. int addr_size = 0,

26、recv_len = 0;14.15. /*初始化操作sock需要的DLL*/16. WSAStartup(MAKEWORD(2,2),&wd);17.18. /*創(chuàng)建服務(wù)端socket */19. if (-1 = (ServerSock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP)20. 21. printf("socket error!n");22. exit(1);23. 24.25. /*設(shè)置服務(wù)端信息 */26. memset(&ServerSockAddr,0, sizeof(ServerSockAddr

27、); /給結(jié)構(gòu)體 ServerSockAddr 清零27. ServerSockAddr.sin_family = AF_INET;/使用IPv4地址28. ServerSockAddr.sin_addr.s_addr = inet_addr("");/本機(jī) IP 地址29. ServerSockAddr.sin_port = htons(1314);/ 端口30.31. /*綁定套接字 */32. if (-1 = bind(ServerSock,(SOCKADDR*)&ServerSockAddr,sizeof(SOCKADDR)33. 34.

28、 printf("bind error!n");35. exit(1);36. 37.38. /*進(jìn)入監(jiān)聽狀態(tài)*/39. if (-1= listen(ServerSock, 10)40. 41. printf("listen error!n");42. exit(1);43. 44.45. addr_size = sizeof(SOCKADDR);46.47. while (1)48. 49. /*監(jiān)聽客戶端請求,accept函數(shù)返回一個(gè)新的套接字,發(fā)送和接收都是用這個(gè)套接字*/50. if (-1 = (ClientSock = accept(Ser

29、verSock,(SOCKADDR*)&ClientAddr, &addr_size)51. 52. printf("socket error!n");53. exit(1);54. 55.56. /*接受客戶端的返回?cái)?shù)據(jù) */57. intrecv_len = recv(ClientSock, Buf,BUF_LEN, 0);58. printf("汆戶端發(fā)送過來的數(shù)據(jù)為:sn", Buf);59.60. /*發(fā)送數(shù)據(jù)到客戶端 */61. send(ClientSock, Buf, recv_len, 0);62.63. /*關(guān)閉客戶端

30、套接字*/64. closesocket(ClientSock);65.66. /*清空緩沖區(qū) */67. memset(Buf, 0, BUF_LEN);68. 69.70. /*如果有退出循環(huán)的條件,這里還需要清除對(duì)socket庫的使用*/71. /*關(guān)閉服務(wù)端套接字 */72. /closesocket(ServerSock);73. /*WSACleanup();*/74.75. return 0;76. 客戶端程序 tcp_client.c :1. #include<stdio.h>2. #include <winsock2.h>3.4. #define BU

31、F_LEN 1005.6. int main(void)7. 8. WSADATAwd;9. SOCKET ClientSock;10. char BufBUF_LEN =0;11. SOCKADDR_IN ServerSockAddr;12.13. /*初始化操作sock需要的DLL*/14. WSAStartup(MAKEWORD(2,2),&wd);15.16. /*向服務(wù)器發(fā)起請求 */17. memset(&ServerSockAddr, 0, sizeof(ServerSockAddr);18. ServerSockAddr.sin_family = AF_INET

32、;19. ServerSockAddr.sin_addr.s_addr = inet_addr("");20. ServerSockAddr.sin_port = htons(1314);21.22. while (1)23. 24. /*創(chuàng)建客戶端socket */25. if (-1 = (ClientSock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP)26. 27. printf("socket error!n");28. exit(1);29. 30. if (-1= connect(C

33、lientSock, (SOCKADDR*)&ServerSockAddr,sizeof(SOCKADDR)31. 32. printf("connect error!n");33. exit(1);34. 35. printf("請輸入一個(gè)字符用,發(fā)送給服務(wù)端:");36. gets(Buf);37. /*發(fā)送數(shù)據(jù)到服務(wù)端 */38. send(ClientSock, Buf, strlen(Buf), 0);39.40. /*接受服務(wù)端的返回?cái)?shù)據(jù) */41. recv(ClientSock, Buf, BUF_LEN, 0);42. prin

34、tf("服務(wù)端發(fā)送過來的藪據(jù)為: %sn", Buf);43.44. memset(Buf, 0, BUF_LEN); / 重置緩沖區(qū)45. closesocket(ClientSock); / 關(guān)閉套接字46. 47.48. /WSACleanup();/*如果有退出循環(huán)的條件,這里還需要清除對(duì)socket庫的使用*/49. return 0;50. 我們上邊的IP地址概念那一部分中,有強(qiáng)調(diào) 這個(gè)IP是 個(gè)特殊的IP地址,這是回送地址,即本地機(jī),一般用來測試使用。這個(gè)例 子中我們就用到了。止匕外,端口我們設(shè)置為1314,這是隨意設(shè)置的,只要范圍在 10

35、2465536之間就可以。1.2.本文使用的是gcc編譯器編譯,編譯命令如下:gcc tcp_client.c -o tcp_client.exe -lwsock32gcc tcp_server.c -o tcp_server.exe -lwsock32這里必須要加 -lwsock32 這個(gè)參數(shù)用于鏈接 windows下socket編程 必須的winsock2這個(gè)庫。若是使用集成開發(fā)環(huán)境,則需要把wsock32.lib放在工程目錄下,并在我們代碼中#include<winsock2.h>下面加上一行 #pragmacomment(lib,"ws2_32.lib"

36、) 代碼。實(shí)驗(yàn)現(xiàn)象:一先啟動(dòng)服務(wù)端程序 tcp_server.exe,再啟動(dòng)客戶端程序tcp_client.exe并在客戶端中輸入字符串,則當(dāng)服務(wù)端會(huì)接收到字符串時(shí)會(huì)打印輸儲(chǔ),與此同時(shí)也會(huì)往客戶端返回相同的數(shù)據(jù):fkIIcjeril exf J端。品式瑞 當(dāng)n M對(duì)科 we艮2 一戶 uu. bhm rr. rj FI Ehr 給 充運(yùn)十法 第VTS.H ,我,砂 串的事的串 府來n來符 771,.丁了!字 -麥需 一 /.端諾(2) Linux的程序:在linux下,“一切都是文件”,所以這里我們的套接字也當(dāng)做文件來看 待。服務(wù)端程序 linux_ tcp_ server.c :1. #in

37、clude<stdio.h>2. #include <string.h>3. #include <stdlib.h>4. #include <unistd.h>5. #include <arpa/inet.h>6. #include <sys/socket.h>7. #include <netinet/in.h>8.9. #defineBUF_LEN 10010.11. int main(void)12. 13. int ServerFd, ClientFd;14. char BufBUF_LEN = 0;15

38、. struct sockaddr ClientAddr;16. int addr_len = 0, recv_len = 0;17. struct sockaddr_in ServerSockAddr;18. int optval = 1;19.20. /*創(chuàng)建服務(wù)端文件描述符*/21. if (-1 = (ServerFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)22. 23. printf("socket error!n");24. exit(1);25. 26.27. /*設(shè)置服務(wù)端信息 */28.29. memset(

39、&ServerSockAddr, 0, sizeof(ServerSockAddr);/ 給結(jié)構(gòu)體 ServerSockAddr 清零30. ServerSockAddr.sin_family = AF_INET;/使用IPv4地址31. ServerSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);/自動(dòng)獲取IP地址32. ServerSockAddr.sin_port = htons(6666);/ 端口33.34.35. /設(shè)置地址和端口號(hào)可以重復(fù)使用36. if (setsockopt(ServerFd, SOL_SOCKET,SO_RE

40、USEADDR, &optval,sizeof(optval) < 0)37. 38. printf("setsockopt error!n");39. exit(1);40. 41.42. /*綁定操作,綁定前加上上面的socket屬性可重復(fù)使用地址*/43. if (-1 = bind(ServerFd, (struct sockaddr*)&ServerSockAddr,sizeof(struct sockaddr)44. 45. printf("bind error!n");46. exit(1);47. 48.49. /*

41、進(jìn)入監(jiān)聽狀態(tài)*/50. if (-1=(listen(ServerFd, 10)51. 52. printf("listen error!n");53. exit(1);54. 55.56. addr_len = sizeof(struct sockaddr);57.58. while (1)59. 60. /*監(jiān)聽客戶端請求,accept函數(shù)返回一個(gè)新的套接字,發(fā)送和接收都是用這個(gè)套接字*/61. if (-1 = (ClientFd = accept(ServerFd, (structsockaddr*)&ClientAddr, &addr_len)62

42、. 63. printf("accept error!n");64. exit(1);65. 66.67. /*接受客戶端的返回?cái)?shù)據(jù)*/68. if(recv_len= recv(ClientFd, Buf, BUF_LEN, 0) < 0)69. 70. printf("recv error!n");71. exit(1);72. 73.74. printf("客戶端發(fā)送過來的數(shù)據(jù)為:%sn", Buf);75.76. /*發(fā)送數(shù)據(jù)到客戶端 */77. send(ClientFd, Buf, recv_len, 0);78.7

43、9. /*關(guān)閉客戶端套接字*/80. close(ClientFd);81.82. /*清空緩沖區(qū) */83. memset(Buf, 0, BUF_LEN);84. 85.86. return 0;87. 客戶端程序 linux_ tcp_ client.c :1. #include<stdio.h>2. #include <string.h>3. #include <stdlib.h>4. #include <unistd.h>5. #include <arpa/inet.h>6. #include <sys/socket.

44、 h>7.8. #defineBUF_LEN 1009.10. int main(void)11. 12. int ClientFd;13. char BufBUF_LEN = 0;14. struct sockaddr_in ServerSockAddr;15.16.17. /*向服務(wù)器發(fā)起請求 */18. memset(&ServerSockAddr, 0, sizeof(ServerSockAddr);19. ServerSockAddr.sin_family = AF_INET;20. ServerSockAddr.sin_addr.s_addr = inet_addr(

45、"");21. ServerSockAddr.sin_port = htons(6666);22.23. while (1)24. 25. /*創(chuàng)建客戶端socket */26. if (-1 = (ClientFd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP)27. 28. printf("socket error!n");29. exit(1);30. 31.32. /* 連接*/33. if (-1 =connect(ClientFd,(struct sockaddr*)&Serve

46、rSockAddr,sizeof(ServerSockAddr)34. 35. printf("connect error!n");36. exit(1);37. 38.39. printf("請輸入一個(gè)字符用,發(fā)送給服務(wù)端:");40. gets(Buf);41. /*發(fā)送數(shù)據(jù)到服務(wù)端 */42. send(ClientFd, Buf, strlen(Buf), 0);43. memset(Buf, 0, BUF_LEN);/ 重置緩沖區(qū)44.45. /*接受服務(wù)端的返回?cái)?shù)據(jù) */46. recv(ClientFd, Buf, BUF_LEN, 0);

47、47. printf("服務(wù)端發(fā)送過來的數(shù)據(jù)為:%sn", Buf);48.49. memset(Buf, 0, BUF_LEN); / 重置緩沖區(qū)50. close(ClientFd); / 關(guān)閉套接字51. 52.53. return 0;54. Linux下編譯就不需要添加-lwsock32參數(shù):1.2.gcc linux_tcp_server.c -o linux_tcp_server gcc linux_tcp_client.c -o linux_tcp_client實(shí)驗(yàn)現(xiàn)象7 一一 一二年程序骨后盲? 9 *中其二胡 25O4;24 hn在調(diào)試這份程序時(shí),出現(xiàn)了

48、綁定錯(cuò)誤:文件任編耨歸竟看漢)搜索終端任)幫助出) Iznlocalhot SocketTestB ,/linux tcp server bind error,Iznlocalhost SocketTestJS |經(jīng)上網(wǎng)查詢發(fā)現(xiàn)是端口重復(fù)使用,可以在調(diào)用 bind()函數(shù)之前調(diào) 用 setsockopt()函數(shù)以解決端口重復(fù)使用的問題:段董姓短蘭舄口號(hào)可,當(dāng)要使用if (setacckopt; (ezvcrrd r SOL SOZKET , SREtlSEAE'DR e fizp* tdI p sLzeof (DptTal) <)Ip f xntrf (,R .7. . ; L

49、_ r J: o £ - -L P ) rftJti t ();/-克定或fE-a宅配70上上面的.8%二厘也Ht復(fù)里用地te -/if (3. bind(Strverfd (struct aoekaddf*)&SeE-TersackAddri 41ieoE(struct socX&ddr) (printt( . - : .j ');kLe)t2、基于UDP的本地客戶端、服務(wù)端信息交互實(shí)例(1) windows 的程序K 務(wù)端程序 udp_server.c :1. #include<stdio.h>2. #include <winsock2.

50、h>3.4. #defineBUF_LEN 1005.6. int main(void)7. 8. WSADATAwd;9. SOCKET ServerSock;10. char BufBUF_LEN = 0;11. SOCKADDR ClientAddr;12. SOCKADDR_IN ServerSockAddr;13. int addr_size = 0;14.15.16. /*初始化操作sock需要的DLL*/17. WSAStartup(MAKEWORD(2,2),&wd);18.19. /*創(chuàng)建服務(wù)端socket */20. if(-1 = (ServerSock =

51、 socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP)21. 22. printf("socket error!n");23. exit(1);24. 25.26. /*設(shè)置服務(wù)端信息 */27. memset(&ServerSockAddr, 0, sizeof(ServerSockAddr);/給結(jié)構(gòu)體 ServerSockAddr 清零28. ServerSockAddr.sin_family = AF_INET;/使用IPv4地址29. ServerSockAddr.sin_addr.s_addr = htonl(INADDR_AN

52、Y);/ 自動(dòng)獲取IP地址30. ServerSockAddr.sin_port = htons(1314);/ 端口31.32. /*綁定套接字 */33.34. if (-1 = (bind(ServerSock, (SOCKADDR*)&ServerSockAddr,sizeof(SOCKADDR)35. 36. printf("bind error!n");37. exit(1);38. 39.40. addr_size = sizeof(SOCKADDR);41.42. while (1)43. 44. /*接受客戶端的返回?cái)?shù)據(jù)*/45. int str_

53、len = recvfrom(ServerSock, Buf, BUF_LEN, 0, &ClientAddr,&addr_size);46.47. printf("客戶端發(fā)送過來的數(shù)據(jù)為:sn", Buf);48.49. /*發(fā)送數(shù)據(jù)到客戶端 */50. sendto(ServerSock, Buf, str_len, 0, &ClientAddr, addr_size);51.52. /*清空緩沖區(qū) */53. memset(Buf, 0, BUF_LEN);54. 55.56. /*如果有退出循環(huán)的條件,這里還需要清除對(duì) socket庫的使用*

54、/57. /*關(guān)閉服務(wù)端套接字*/58. /closesocket(ServerSock);59. /* WSACleanup();*/60.61. return 0;62. 客戶端程序 udp client.c:1. #include <stdio.h>2. #include <winsock2.h>3.4. #define BUF_LEN 1005.6. int main(void)7. 8. WSADATAwd;9. SOCKET ClientSock;10. char BufBUF_LEN = 0;11. SOCKADDR ServerAddr;12. SOCK

55、ADDR_IN ServerSockAddr;13. int ServerAddrLen = 0;14.15. /*初始化操作sock需要的DLL*/16. WSAStartup(MAKEWORD(2,2),&wd);17.18. /*創(chuàng)建客戶端 socket */19. if (-1 = (ClientSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)20. 21. printf("socket error!n");22. exit(1);23. 24.25. /*向服務(wù)器發(fā)起請求 */26. memset(&S

56、erverSockAddr, 0, sizeof(ServerSockAddr);27. ServerSockAddr.sin_family = PF_INET;28. ServerSockAddr.sin_addr.s_addr = inet_addr("");29. ServerSockAddr.sin_port = htons(1314);30.31. ServerAddrLen = sizeof(ServerAddr);32.33. while (1)34. 35. printf("請輸入一個(gè)字符用,發(fā)送給服務(wù)端:");36. gets(Buf);37. /*發(fā)送數(shù)據(jù)到服務(wù)端 */38. sendto(ClientSock, Buf, strlen(Buf),0, (struct

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論