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 }
輸出的結果爲