VC++ TCP網路控制檯程式
阿新 • • 發佈:2019-02-07
在Windows7系統下,採用工具為VS2008,Win32控制檯應用程式,編寫一個基於TCP的Client/Server網路程式。
1、伺服器端程式碼
#include <WinSock2.h> #include <stdio.h> #define SERVERPORT 6000 //服務埠號 int main(int argc, char *argv[]) { //載入套接字型檔 WORD wVersionRequested;//用於儲存WinSock庫的版本號 WSADATA wsaData; int err; printf("This is a Server side application!\n"); wVersionRequested = MAKEWORD(2,2); err = WSAStartup( wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup() called failed!\n"); return -1; } else { printf("WSAStartup() called successful!\n"); } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { //若不是所請求的版本號2.2,則終止WinSock庫的使用 WSACleanup(); return -1; } //建立用於監聽的套接字 SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0); if(sockServer == INVALID_SOCKET) { printf("socket() called failed! ,error code is: %d", WSAGetLastError()); return -1; } else { printf("socket() called successful!\n"); } //填充伺服器端套接字結構 SOCKADDR_IN addrServer; addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//將主機位元組順序轉換成TCP/IP網路位元組順序 addrServer.sin_family = AF_INET; addrServer.sin_port = htons(SERVERPORT); //將套接字繫結到一個本地地址和埠上 err = bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); if (err == SOCKET_ERROR) { printf("bind() called failed! The error code is: %d\n", WSAGetLastError()); return -1; } else { printf("bind() called successful\n"); } //將套接字設定為監聽模式,準備接收客戶請求 err = listen(sockServer, 5); if (err == SOCKET_ERROR) { printf("listen() called failed! The error code is: %d\n", WSAGetLastError()); return -1; } else { printf("listen() called successful!\n"); } SOCKADDR_IN addrClient; //儲存傳送請求連線的客戶端的套接字資訊 int len = sizeof(SOCKADDR); while(1) { //等待客戶請求到來 SOCKET sockConn = accept(sockServer, (SOCKADDR*)&addrClient, &len); if (sockConn == INVALID_SOCKET) { printf("accept() called falied! The error code is: %d\n", WSAGetLastError()); } else { printf("The Server receive a new client connection!\n"); } char sendBuf[100]; sprintf_s(sendBuf, 100, "Welcome %s",inet_ntoa(addrClient.sin_addr)); //傳送資料 send(sockConn, sendBuf, strlen(sendBuf)+1 , 0); char recvBuf[100]; //接收資料 recv(sockConn, recvBuf, 100, 0); //列印接收到的資料 printf("receive data from client side [%s,%d] is: %s\n", inet_ntoa(addrClient.sin_addr), addrClient.sin_port, recvBuf); closesocket(sockConn); //關閉連線套接字 } return 0; }
2、客戶端程式碼
#include <WinSock2.h> #include <stdio.h> #define SERVERPORT 6000 //服務埠號 #pragma comment(lib, "WS2_32.lib"); int main(int argc, char *argv[]) { //載入套接字型檔 WORD wVersionRequested; WSAData wsaData; int err; printf("This is a Client side application!\n"); wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ printf("WSAStartup() called failed!\n"); return -1; } else { printf("WSAStartup() called successful!\n"); } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return -1; } /* The WinSock DLL is acceptable. Proceed. */ //建立套接字 SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); if(sockClient == INVALID_SOCKET) { printf("socket() called failed! ,error code is: %d", WSAGetLastError()); return -1; } else { printf("socket() called successful!\n"); } //需要連線的服務端套接字結構資訊 SOCKADDR_IN addrServer; addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//設定伺服器的IP地址 addrServer.sin_family = AF_INET; addrServer.sin_port = htons(SERVERPORT);//設定伺服器的埠號(使用網路位元組序) //向伺服器發出連線請求 err = connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); if (err == SOCKET_ERROR) { printf("connect() called failed! The error code is: %d\n", WSAGetLastError()); return -1; } else { printf("connect() called successful\n"); } //接收資料 char recvBuf[100]={0}; recv(sockClient, recvBuf, 100, 0); printf("receive data from server side is: %s\n", recvBuf); //傳送資料 send(sockClient, "This is a client side!\n", strlen("This is a client side!\n")+1, 0); //關閉套接字 closesocket(sockClient); //終止套接字型檔的使用 WSACleanup(); return 0; }
另外,需要注意的是需要在伺服器和客戶端都需要連結WinSock靜態連結庫Ws2_32.lib,有兩種新增方法
方法一:在工程配置屬性中新增
假如建立一個名為TCPClient的Win32控制檯應用程式
在VC2008中新增靜態連結庫WS2_32.lib的方法如下:
(1)切換到TCPServer的【Solution Explorer】,選擇選單【Project】->【TCPClient Properties】
(2)在TCPClient Properties Pages對話方塊中,依次選擇【Configuration Properties】->【Linker】->【Input】,在右側的【Addtional Dependencies】中新增Ws2_32.lib庫。
如下如所示:
伺服器TCPServer也需要連結Ws2_32.lib庫,方法和客戶端TCPClient一樣。
程式結果執行如下:
先啟動伺服器端程式TCPServer,結果如下:
再啟動客戶端TCPClient,客戶端結果如下:
伺服器端TCPServer結果如下:
方法二:在程式碼中新增
#pragma comment(lib, "WS2_32.lib");
參考資料:
1、《VC++深入詳解》 第14章網路程式設計 ,孫鑫主編