網絡編程:實現一個基於Windows的服務端/客戶端程序

widows下使用socket套接字進行網絡通信的步驟與Linux下差異不大,基本的調用流程也是相似的,即使內部的實現有所不同。

以下是服務器端的代碼實現:

#include <iostream>
#include <stdlib.h>
#include <WinSock2.h>
using namespace std;

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		cout << "invalid parameter! add port!" << endl;
		exit(1);
	}

	WSADATA wsaData;
	SOCKET servSock, clntSock;
	SOCKADDR_IN servAddr, clntAddr;
	int clntAddrLen;

	// 設置程序中用到的Winsock版本,並初始化相應版本的庫
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		cout << "WSAStartup() error" << endl;
		exit(1);
	}

	// 創建socket套接字
	servSock = socket(PF_INET, SOCK_STREAM, 0);
	if (servSock == INVALID_SOCKET)
	{
		cout << "socket() error" << endl;
		exit(1);
	}

	// 設置服務端的地址信息:IP、端口、協議族
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(atoi(argv[1]));

	// 綁定IP和端口
	if (bind(servSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
	{
		cout << "bind() error" << endl;
		exit(1);
	}

	// 在所綁定的端口號做監聽
	if (listen(servSock, 5) == SOCKET_ERROR)
	{
		cout << "listen() error" << endl;
		exit(1);
	}

	// 接收來自客戶端的連接請求
	clntAddrLen = sizeof(clntAddr);
	clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &clntAddrLen);
	if (clntSock == INVALID_SOCKET)
	{
		cout << "accept() error" << endl;
		exit(1);
	}

	// 向客戶端發送數據
	char message[] = "Hello, It's servers!";
	send(clntSock, message, sizeof(message), 0);

	// 關閉套接字連接
	closesocket(servSock);
	closesocket(clntSock);

	// 註銷使用的Winsock庫
	WSACleanup();

	return EXIT_SUCCESS;
}

以下是客戶端的代碼實現:

#define _WINSOCK_DEPRECATED_NO_WARNINGS 
#include <iostream>
#include <stdlib.h>
#include <WinSock2.h>
using namespace std;

int main(int argc, char* argv[])
{
	// 檢查輸入參數的合法性
	if (argc != 3)
	{
		cout << "invalid parameter! add ip and port!" << endl;
		exit(1);
	}

	WSADATA wsaData;
	SOCKET clntSocket;
	SOCKADDR_IN servAddr;

	// 設置程序中用到的Winsock版本,並初始化相應版本的庫
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		cout << "WSAStartup() error" << endl;
		exit(1);
	}

	// 創建socket套接字
	clntSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (clntSocket == INVALID_SOCKET)
	{
		cout << "socket() error" << endl;
		exit(1);
	}

	// 設置服務器端的地址信息:IP、端口、協議族
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr(argv[1]);
	servAddr.sin_port = htons(atoi(argv[2]));

	// 創建連接
	if (connect(clntSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
	{
		cout << "connect() error" << endl;
		exit(1);
	}

	// 接收來自服務器端的數據
	char message[100] = { 0 };
	int msglen = recv(clntSocket, message, sizeof(message) - 1, 0);
	if (msglen == -1)
	{
		cout << "recv() error" << endl;
		exit(1);
	}

	cout << "msg from server : " << message << endl;

	// 關閉套接字連接
	closesocket(clntSocket);

	// 註銷使用的Winsock庫
	WSACleanup();

	return 0;
}

在VS中編譯後,生成可執行文件。然後使用cmd,分別運行客戶端和服務器端程序,服務器端監聽8888端口,而客戶端綁定本地IP和8888端口,與服務器端建立鏈接。

客戶端程序執行結果:建立連接成功後,收到來自服務器端的信息數據。
客戶端執行結果

服務器端執行結果:開始時創建套接字,然後等待客戶端的連接,沒有任何輸出,一旦客戶端連接成功後,發送消息,然後直接運行結束。在這裏插入圖片描述

謝謝閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章