首先介紹下計算機通訊系統互聯參考模型OSI (Open System Interconnection) 編程
TCP/IP模型分爲四層結構: 服務器
應用層:至關於OSI模型的上面三層,包括各類應用程序和協議,協議有HTTP,FTP等等
傳輸層:包括TCP、UDP協議
網絡層:IP、ARP、RARP、ICMP協議
數據鏈路層:至關於OSI模型的下面兩層,通俗點說這一層就是網卡驅動和網卡物理設備。
sockets編程發生在應用層和傳輸層之間。
接下來以一個簡單的TCP通訊程序做爲示例:
編譯器Visual Stdio 2012,實現代碼C++。
Server Code:
網絡
// Server.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #include "winsock2.h" #define BUF_SZIE 64 #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { WSADATA wsad; //WSADATA變量 SOCKET Server; //服務器套接字 SOCKET Client; //客戶端套接字 SOCKADDR_IN addrServ; //服務器地址 char buf[BUF_SZIE]; //接收數據緩衝區 int retVal; //返回值 //初始化套接字動態庫 if (WSAStartup(MAKEWORD(2,2),&wsad) != 0) { printf("初始化套接字動態庫失敗!\n"); return 1; } //建立套接字 Server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == Server) { printf("建立套接字失敗!\n"); WSACleanup();//釋放套接字資源; return -1; } //服務器套接字地址 addrServ.sin_family = AF_INET; addrServ.sin_port = htons(2012); addrServ.sin_addr.s_addr = INADDR_ANY; //綁定套接字 retVal = bind(Server, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN)); if(SOCKET_ERROR == retVal) { printf("綁定套接字失敗!\n"); closesocket(Server); //關閉套接字 WSACleanup(); //釋放套接字資源; return -1; } //開始監聽 retVal = listen(Server, 1); if(SOCKET_ERROR == retVal) { printf("監聽失敗!\n"); closesocket(Server); //關閉套接字 WSACleanup(); //釋放套接字資源; return -1; } //接受客戶端請求 sockaddr_in addrClient; int addrClientlen = sizeof(addrClient); Client = accept(Server,(sockaddr FAR*)&addrClient, &addrClientlen); if(INVALID_SOCKET == Client) { printf("接受客戶端請求失敗!\n"); closesocket(Server); //關閉套接字 WSACleanup(); //釋放套接字資源; return -1; } //接收客戶端數據 ZeroMemory(buf, BUF_SZIE); retVal = recv(Client, buf, BUF_SZIE, 0); if (SOCKET_ERROR == retVal) { printf("接收客戶端請求失敗!\n"); closesocket(Server); //關閉套接字 closesocket(Client); //關閉套接字 WSACleanup(); //釋放套接字資源; return -1; } printf("%s\n", buf); //輸出來自Client的字符串 //退出 closesocket(Server); //關閉套接字 closesocket(Client); //關閉套接字 WSACleanup(); //釋放套接字資源; return 0; }Client Code:
// Client.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #define BUF_SZIE 64 #include "winsock2.h" #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { WSADATA wsad; //WSADATA變量 SOCKET sHost; //服務器套接字 SOCKADDR_IN servAddr; //服務器地址 char buf[BUF_SZIE]; //接收數據緩衝區 int retVal; //返回值 //初始化套接字動態庫 if (WSAStartup(MAKEWORD(2,2), &wsad) != 0) { printf("初始化套接字失敗!\n"); return -1; } //建立套接字 sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == sHost) { printf("建立套接字失敗!\n"); WSACleanup();//釋放套接字資源 return -1; } //設置服務器地址 servAddr.sin_family =AF_INET; servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons((short)2012); int nServAddlen = sizeof(servAddr); //鏈接服務器 retVal=connect(sHost,(LPSOCKADDR)&servAddr, sizeof(servAddr)); if(SOCKET_ERROR == retVal) { printf("鏈接服務器失敗!\n"); closesocket(sHost); //關閉套接字 WSACleanup(); //釋放套接字資源 return -1; } //向服務器發送數據 ZeroMemory(buf, BUF_SZIE); strcpy(buf, "2012年12月13日"); retVal = send(sHost, buf, strlen(buf), 0); if (SOCKET_ERROR == retVal) { printf("發送數據失敗!\n"); closesocket(sHost); //關閉套接字 WSACleanup(); //釋放套接字資源 return -1; } //退出 closesocket(sHost); //關閉套接字 WSACleanup(); //釋放套接字資源 return 0; }雖然說該程序比較簡單,可是麻雀雖小五臟俱全,程序代碼旨在突出開發TCP應用程序的框架,其中Server 、Client調用Windows Sockets API的過程以下所示:
程序運行結果: 框架
轉載請註明出處,謝謝!
socket