Windows Socket的UDP和TCP編程介紹

1:網絡中進程之間如何通訊ios

  爲了實現進程之間通訊,首要解決的問題是如何惟一標識一個進程,在本地能夠經過進程PID來惟一標識一個進程,可是在網絡中則是行不通的,其實TCP/IP協議族已經幫咱們解決了這個問題,網絡層的"ip 地址"能夠惟一標識網絡中的主機,而"傳輸層的 協議+端口"能夠惟一標識主機中的應用程序(進程)。這樣利用(ip地址,謝謝,端口)就能夠標識網絡中的進程了,網絡中的進程通訊就能夠利用這個標誌與其它進程進行交互。而如今幾乎全部網絡應用程序都是採用socket來通訊的,那麼什麼是socket呢?編程

2:套接字(socket)windows

  socket起源於Unix,而Unix/Linux基本哲學之一就是"一切皆文件",均可以用"打開Open -> 讀寫write/read ->關閉close"模式來操做,socket就是該模式的一個實現,socket就是一種特殊的文件,一些socket函數就是對其進行的操做(讀/寫IO、打開、關閉),說白了Socket就是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。socket把複雜的TCP/IP協議族隱藏在socket接口後面,對用戶來講就是一組簡單的接口。讓socket去組織數據,以符合指定的協議。服務器

  隨着Unix的應用推廣,套接字有被引進了windows等操做系統,套接字一般只與同一區域的套接字交換數據,windows只支持一個通訊區域,網際域(AF_INET),這個域被使用網際協議簇的通訊進程。網絡

3:客戶機/服務器模式socket

  在TCP/IP網絡應用中,通訊的兩個進程間相互做用的主要模式是客戶機/服務器模式(client/server),即客戶向服務器提出請求,服務器接受到請求後提出相應的服務。tcp

服務器:函數

 (1):首先服務器先要啓動,打開一個通訊通道並告知本機,它願意在某一個地址和端口上接收客戶請求。spa

 (2):等待客戶請求到達該端口。操作系統

 (3):接收服務請求,處理該客戶請求,服務完成後,關閉此進程與客戶的通訊鏈路,並終止。

 (4):返回第二步,等待另外一個客戶請求

 (5):關閉服務器

客戶方:

 (1):打開一個通訊通道,並鏈接到服務器所在的主機特定的端口。

 (2):向服務器發送請求,等待並接收應答,繼續提出請求。

 (3):請求結束後關閉通訊信道並終止

4:基於TCP(面向鏈接)的socket編程

  

服務器端先初始化Socket,而後與端口綁定(bind),對端口進行監聽(listlen),調用accept阻塞,等待客戶端鏈接。在這時若是有個客戶端初始化一個Socket,而後鏈接服務器(connect),若是鏈接成功,這時客戶端與服務器端的鏈接就創建了,客戶端發送數據請求,服務器端接收請求並處理請求,而後把迴應數據發送給客戶端,客戶端讀取數據,最後關閉鏈接,一次交互結束。

5:基於UDP(面向無鏈接)的socket編程

  

服務器先建立socket,將socket綁定(bind)一個本地地址和端口上,等待數據傳輸(recvfrom).這個時候若是有個客戶端建立socket,而且向服務器發送數據(sendto),服務器就創建了鏈接,實現了數據的通訊,鏈接結束後關閉鏈接.

6:UDP例子

   Server端

 1 //注:須要在stdafx.h 裏面添加 #pragma comment(lib, "ws2_32.lib")
 2 #include"stdafx.h"
 3 #include <winsock2.h>
 4 #include <ws2tcpip.h>
 5 #include <stdio.h>
 6 #include <windows.h>
 7 using namespace std;  
 8 
 9 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
10 
11 int main()
12 {
13     WORD wVersionRequested;
14     WSADATA wsaData;
15     int err;
16 
17     wVersionRequested = MAKEWORD(2, 2);
18 
19     err = WSAStartup(wVersionRequested, &wsaData);
20     if (err != 0) 
21     {                                 
22         printf("WSAStartup failed with error: %d\n", err);
23         return 1;
24     }
25 
26     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
27     {
28         printf("Could not find a usable version of Winsock.dll\n");
29         WSACleanup();
30         return 1;
31     }
32     else
33     {
34         printf("The Winsock 2.2 dll was found okay\n");
35     }
36 
37     SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM, 0); //建立一個socket句柄;
38     if( sockSrv == INVALID_SOCKET )
39     {  
40         printf("socket() fail:%d\n",WSAGetLastError());
41         return -2;  
42     } 
43 
44     SOCKADDR_IN  addrServ;
45     memset(&addrServ,0,sizeof(addrServ));
46     addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
47     addrServ.sin_family = AF_INET;
48     addrServ.sin_port = htons(4999); //從"主機字節順序" 轉變爲 "網絡字節順序"
49 
50     err = bind(sockSrv,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); //把socket 綁定到指定地址上
51     if( err != 0 )  
52     {  
53         printf("bind()fail:%d\n",WSAGetLastError());  
54         return -3;  
55     } 
56 
57     SOCKADDR_IN  addrClient;
58     memset(&addrClient,0,sizeof(addrClient)); //在設置每一個地址成員以前,整個addr結構應該被初始化0;
59     int length = sizeof(SOCKADDR);
60     char recvBuf[100];
61     printf("waiting for client connect!!!!\n");
62     recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&length);
63 
64     printf("recvfrom client:: %s\n",recvBuf);
65 
66     closesocket(sockSrv);
67 
68     WSACleanup();
69 
70     system("PAUSE");
71     return 0;
72 }

Client端

 1 // 注:須要在stdafx.h 裏面添加 #pragma comment(lib, "ws2_32.lib")
 2 //
 3 #include"stdafx.h"
 4 #include <winsock2.h>
 5 #include <ws2tcpip.h>
 6 #include <stdio.h>
 7 #include <windows.h>
 8 using namespace std;  
 9 
10 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
11 
12 int main()
13 {
14     WORD wVersionRequested;
15     WSADATA wsaData;
16     int err;
17 
18     wVersionRequested = MAKEWORD(2, 2);
19 
20     err = WSAStartup(wVersionRequested, &wsaData);
21     if (err != 0) 
22     {                                 
23         printf("WSAStartup failed with error: %d\n", err);
24         return 1;
25     }
26 
27     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
28     {
29         printf("Could not find a usable version of Winsock.dll\n");
30         WSACleanup();
31         return 1;
32     }
33     else
34     {
35         printf("The Winsock 2.2 dll was found okay\n");
36     }
37 
38 
39     SOCKET sockClient = socket(AF_INET,SOCK_DGRAM, 0);
40 
41     SOCKADDR_IN  addrServ;
42     memset(&addrServ,0,sizeof(addrServ));
43     addrServ.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
44     addrServ.sin_family = AF_INET;
45     addrServ.sin_port = htons(4999);
46     printf("begin to send data to server::Hello\n");
47     sendto(sockClient,"Hello\n",strlen("Hello\n")+1,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
48 
49     closesocket(sockClient);
50 
51     system("PAUSE");
52     WSACleanup();
53 
54     return 0;
55 }

輸出的結果爲:

 7:TCP例子

 Server端

 1 #include"stdafx.h"
 2 #include <winsock2.h>  
 3 #include <iostream>  
 4 
 5 #include <string.h>  
 6 using namespace std;  
 7 
 8 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
 9 
10 
11 const int DEFAULT_PORT = 8000;  
12 int main(int argc,char* argv[])  
13 {  
14 
15     WORD    wVersionRequested;  
16     WSADATA wsaData;  
17     int     err,iLen;  
18     wVersionRequested   =   MAKEWORD(2,2);  
19 
20     err =  WSAStartup(wVersionRequested,&wsaData); 
21     if( err!=0 )  
22     {  
23         printf("WSAStartup failed with error: %d\n", err); 
24         return -1;  
25     }  
26     if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) 
27     {
28         printf("Could not find a usable version of Winsock.dll\n");
29         WSACleanup();
30         return 1;
31     }
32     else
33     {
34         printf("The Winsock 2.2 dll was found okay\n");
35     }
36 
37     SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);  
38     if( sockSrv == INVALID_SOCKET )
39     {  
40         printf("socket() fail:%d\n",WSAGetLastError());
41         return -2;  
42     }  
43 
44     SOCKADDR_IN addrSrv;  
45     memset(&addrSrv,0,sizeof(addrSrv));
46     addrSrv.sin_family = AF_INET;  
47     addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);  
48     addrSrv.sin_port = htons(DEFAULT_PORT);  
49 
50     err = bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));  
51     if( err != 0 )  
52     {  
53         printf("bind()fail:%d\n",WSAGetLastError());  
54         return -3;  
55     }  
56 
57     err = listen( sockSrv,5 );//listen函數的第一個參數即爲要監聽的socket描述字,第二個參數爲相應socket能夠排隊的最大鏈接個數
58     if( err != 0 )  
59     {  
60         printf("listen()fail:%d\n",WSAGetLastError());
61         return -4;  
62     } 
63     printf("Server waitting...!!!!!\n");  
64     SOCKADDR_IN addrClt;  
65     int len = sizeof(SOCKADDR);  
66     memset(&addrClt,0,len);
67 
68     while(1)  
69     {  
70         SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClt,&len);  
71         char sendBuf[1024],hostname[100];  
72         if( gethostname(hostname,100) != 0 ) 
73         {
74             strcpy_s(hostname,strlen("None")+1,"None");  
75         }
76         sprintf_s(sendBuf,sizeof(sendBuf),"Welecome %s connected to %s!",inet_ntoa(addrClt.sin_addr),hostname);  
77 
78         err = send(sockConn,sendBuf,strlen(sendBuf)+1,0);  
79 
80         char recvBuf[1024]="\0";  
81         iLen = recv(sockConn,recvBuf,1024,0);  
82 
83         recvBuf[iLen]='\0'; 
84         printf(recvBuf);
85 
86         closesocket(sockConn);  
87     }  
88 
89     closesocket(sockSrv);  
90 
91     WSACleanup();  
92     return 0;  
93 }  

Client端

 1 // client.cpp : 定義控制檯應用程序的入口點。
 2 //
 3 #include"stdafx.h"
 4 #include <winsock2.h>  
 5 #include <iostream>  
 6 
 7 #include <string.h>  
 8 using namespace std;  
 9 
10 #pragma comment(lib, "ws2_32.lib")          
11 
12 
13 const int DEFAULT_PORT = 8000;  
14 int main(int argc,char* argv[])  
15 {  
16 
17     WORD    wVersionRequested;  
18     WSADATA wsaData;  
19     int     err,iLen;  
20     wVersionRequested   =   MAKEWORD(2,2);
21 
22     err =   WSAStartup(wVersionRequested,&wsaData); //load win socket  
23     if( err != 0 )  
24     {  
25         printf("WSAStartup failed with error: %d\n", err);
26         return -1;  
27     }  
28 
29     SOCKET sockClt = socket(AF_INET,SOCK_STREAM,0);  
30     if( sockClt == INVALID_SOCKET )
31     {  
32         printf("socket() fail:%d\n",WSAGetLastError());
33         return -2;  
34     }  
35 
36     SOCKADDR_IN addrSrv;  
37     memset(&addrSrv,0,sizeof(addrSrv));
38     addrSrv.sin_family = AF_INET;  
39     addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");  
40     addrSrv.sin_port = htons(DEFAULT_PORT);  
41 
42     err = connect(sockClt,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));  
43 
44     if(err ==INVALID_SOCKET)  
45     {  
46         printf("connect()fail:%d\n",WSAGetLastError());   
47         return -1;  
48     }  
49 
50     char sendBuf[1024],hostname[100];  
51     if( gethostname(hostname,100) != 0 ) //若是沒有錯誤的時候gethostname會返回0;
52     {
53         strcpy_s(hostname,strlen("None")+1,"None");  
54     }
55     strcpy_s(sendBuf,strlen(hostname)+1,hostname);  
56     strcat_s(sendBuf,sizeof(sendBuf)," have connected to you!");  
57     err = send(sockClt,sendBuf,strlen(sendBuf)+1,0);  
58 
59     char recvBuf[1024]="\0";  
60     iLen = recv(sockClt,recvBuf,1024,0);  
61 
62     if( iLen == 0 )  
63     {
64         return -3; 
65     }
66     else if( iLen == SOCKET_ERROR )
67     {  
68         printf("recv() fail:%d\n",WSAGetLastError()); 
69         return -4;  
70     }  
71     else  
72     {  
73         recvBuf[iLen] = '\0';  
74         printf(recvBuf);  
75         printf("\n");
76     }  
77     closesocket(sockClt);  
78 
79     WSACleanup();  
80     system("PAUSE");  
81     return 0;  
82 }  

輸出的結果爲

相關文章
相關標籤/搜索