C++ Winsock服务端和客户端自由交互

发布于 2018-07-27  878 次阅读


服务端

Server.h

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib, "WS2_32")  // 链接到WS2_32.lib   

using std::cin;
using std::cout;
using std::endl;

class Server {
public:
	Server(int _port);
	bool connectClient();
	void closeConnect();

private:
	static void sendFun();
	static void receiveFun();

private:
	char recvBuf[100], sendBuf[100];
	int len;
	WSADATA wsaData;
	SOCKET connectSocket;
	SOCKET serverSocket;
	SOCKADDR_IN serverAddress;
	SOCKADDR_IN clientAddress;
};

static Server * tmp;

Server::Server(int _port) {
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { // 调用函数,指明使用的socket版本!wsaData返回版本信息
		cout << "初始化失败!" << endl;
		cin.get();
		exit(0);
	}
	serverSocket = socket(AF_INET, SOCK_STREAM, 0); // 套接字
	if (serverSocket == -1) {
		cout << "初始化socket失败!" << endl;
		cin.get();
		exit(0);
	}
	serverAddress.sin_family = AF_INET; // 地址族形式
	serverAddress.sin_port = htons(_port); // 1024以上的端口号
	serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // IPv4地址(不确定地址,也表示所有地址)
	int retVal = bind(serverSocket, (LPSOCKADDR)&serverAddress, sizeof(SOCKADDR_IN)); // 将套接字进行地址和端口的绑定
	if (retVal == SOCKET_ERROR) {
		cout << "绑定失败! " << WSAGetLastError() << endl;
		cin.get();
		exit(0);
	}
	if (listen(serverSocket, 10) == SOCKET_ERROR) {
		cout << "监听失败! " << WSAGetLastError() << endl;
		cin.get();
		exit(0);
	}
	tmp = this;
}

bool Server::connectClient() {
	len = sizeof(SOCKADDR);
	while (1) {
		// 等待客户请求到来
		connectSocket = accept(serverSocket, (SOCKADDR*)&clientAddress, &len); // sockConn为连接套接字
		if (connectSocket == SOCKET_ERROR) {
			cout << "等待请求失败!" << WSAGetLastError() << endl;
			break;
		}
		// 发送数据
		char sendbuf[] = "通信已建立!";
		int iSend = send(connectSocket, sendbuf, sizeof(sendbuf), 0);
		if (iSend == SOCKET_ERROR) {
			cout << "发送失败!" << endl;
			break;
		}
		recv(connectSocket, recvBuf, sizeof(recvBuf), 0); // 接收建立起连接的数据
		cout << recvBuf << " 客户端的IP是:" << inet_ntoa(clientAddress.sin_addr) << endl;
		HANDLE sendFunHandle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)sendFun, NULL, NULL, NULL);
		HANDLE receiveFunHandle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)receiveFun, NULL, NULL, NULL);
		CloseHandle(sendFunHandle);
		CloseHandle(receiveFunHandle);
	}
	return false;
}

void Server::closeConnect() {
	closesocket(serverSocket);
	WSACleanup(); // 调用此函数解除与socket库的绑定,并释放socket库所占用的系统资源
	system("pause");
}

void Server::sendFun() {
	while (true) {
		memset(tmp->sendBuf, NULL, sizeof(tmp->sendBuf));
		cin >> tmp->sendBuf;
		cin.get();
		send(tmp->connectSocket, tmp->sendBuf, sizeof(tmp->sendBuf), 0);
	}
	closesocket(tmp->connectSocket);
}

void Server::receiveFun() {
	while (true) {
		memset(tmp->recvBuf, NULL, sizeof(recvBuf));
		//接收数据
		int flag = (int)recv(tmp->connectSocket, tmp->recvBuf, sizeof(recvBuf), 0);
		if (flag > 0) // 有数据才响应
			cout << "接收到的数据为:" << tmp->recvBuf << endl;
	}
	closesocket(tmp->connectSocket);
}

Server.cpp

#include "Server.h"

int main() {
	Server test(8080);
	test.connectClient();
	test.closeConnect();
}

客户端

Client.h

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib, "WS2_32")  // 链接到WS2_32.lib  

using std::cin;
using std::cout;
using std::endl;

class Client {
public:
	Client(const char* _ip, int _port);
	bool connectServer();
	void closeConnect();

private:
	static void sendFun();
	static void receiveFun();

private:
	char buffs[100], buff[100];
	WSADATA wsaData;
	SOCKET clientSocket;
	SOCKADDR_IN serverAddress;
};

static Client* tmp;

Client::Client(const char* _ip, int _port) {
	char buff[1024];
	memset(buff, 0, sizeof(buff));
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		cout << "初始化winsock失败!" << endl;
		cin.get();
		exit(0);
	}
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(_port); // 端口号
	serverAddress.sin_addr.S_un.S_addr = inet_addr(_ip); // IP地址
	clientSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (SOCKET_ERROR == clientSocket) {
		cout << "Socket() error: " << WSAGetLastError() << endl;
		cin.get();
		exit(0);
	}
	tmp = this;
}

bool Client::connectServer() {
	if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == INVALID_SOCKET) { // 向服务器发出连接请求	
		cout << "连接失败!" << WSAGetLastError() << endl;
		cin.get();
		return false;
	}
	else { // 接收数据
		recv(clientSocket, buff, sizeof(buff), 0);
		cout << buff << " 服务端的IP是:" << inet_ntoa(serverAddress.sin_addr) << endl;
	}
	char sendbuffs[] = "通信已建立!"; // 发送数据	
	send(clientSocket, sendbuffs, sizeof(buffs), 0);
	// 在线程中进行数据的收发
	while (true) {
		HANDLE sendFunHandle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)sendFun, NULL, NULL, NULL);
		HANDLE receiveFunHandle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)receiveFun, NULL, NULL, NULL);
		CloseHandle(sendFunHandle);
		CloseHandle(receiveFunHandle);
	}
}

void Client::closeConnect() {
	closesocket(clientSocket);
	WSACleanup(); // 释放初始化Ws2_32.dll所分配的资源
	system("pause");
	cin.get();
}

void Client::sendFun() {
	while (true) {
		memset(tmp->buffs, NULL, sizeof(tmp->buffs));
		cin >> tmp->buffs;
		send(tmp->clientSocket, tmp->buffs, sizeof(tmp->buffs), 0);
	}
	closesocket(tmp->clientSocket);
}

void Client::receiveFun() {
	while (true) {
		memset(tmp->buff, NULL, sizeof(tmp->buff));
		int flag = (int)recv(tmp->clientSocket, tmp->buff, sizeof(tmp->buff), 0);
		if (flag > 0)
			cout << "接收的数据为:" << tmp->buff << endl;
	}
	closesocket(tmp->clientSocket);
}

Client.cpp

#include "Client.h"

int main() {
	Client myClient("127.0.0.1", 8080);
	myClient.connectServer();
	myClient.closeConnect();
}