1.创建(在visual studio)
点击创建新项目
双击空项目
改好项目名称和位置后,点击创建
右键解决方案->选择添加->新建项目
此时会生成两个项目,右键重命名,一个改为ClientSocket,一个改为ServerSocket
在ClientSocket中创建Client.cpp 在ServerSocket中创建Server.cpp
点击源文件->添加->新建项
链接库 ClientSocket和ServerSocket这两个项目都要进行
右键项目->属性
链接器->输入->点下拉列表->点编辑
输入
ws2_32.lib
一直点确定退出就行
(一些头文件是windows自带的,但是使用 Windows Sockets 2 (Winsock) 编程接口时,需要链接 ws2_32.lib
库)
2.服务端
Server.cpp
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <string>
#include <thread>
#pragma comment(lib, "ws2_32.lib")
#define PORT 65432
void Cleanup(SOCKET socket)
{
closesocket(socket);//关闭套接字
WSACleanup(); //清理WSA的资源
}
void HandleClientCommunication(SOCKET clientSocket)
{
std::cout << "成功和" << clientSocket << "建立连接!" << std::endl;
while (true)
{
char buffer[1000];
std::cout << "服务器向" << clientSocket << "发送数据:" << std::endl;
std::cin.getline(buffer, sizeof(buffer));
std::string message = buffer;
int size = send(clientSocket, message.c_str(), static_cast<int>(message.length()), 0);
if (message == "end")
{
std::cout << "关闭和" << clientSocket << "的连接!" << std::endl;
break;
}
else if (size == SOCKET_ERROR || size == 0)
{
std::cout << "[发送信息失败] 错误代码:" << WSAGetLastError() << std::endl;
break;
}
else
{
std::cout << " [信息发送成功]" << std::endl;
}
memset(buffer, 0, sizeof(buffer));
int receivedBytes = recv(clientSocket, buffer, sizeof(buffer), 0);
if (receivedBytes == SOCKET_ERROR || receivedBytes == 0)
{
std::cout << clientSocket << "断开了连接!" << std::endl;
break;
}
else
{
std::cout << clientSocket << " 说: " << buffer << std::endl;
}
}
closesocket(clientSocket);
}
int main()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
std::cout << "加载winsock.dll失败!" << std::endl;
return 0;
}
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
{
std::cout << "创建套接字失败!错误代码:" << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}
sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &serverAddress.sin_addr);
if (bind(serverSocket, reinterpret_cast<SOCKADDR*>(&serverAddress), sizeof(serverAddress)) == SOCKET_ERROR)
{
std::cout << "地址绑定失败!错误代码:" << WSAGetLastError() << std::endl;
Cleanup(serverSocket);
return 0;
}
if (listen(serverSocket, 0) == SOCKET_ERROR)
{
std::cout << "监听失败!错误代码:" << WSAGetLastError() << std::endl;
Cleanup(serverSocket);
return 0;
}
while (true)
{
sockaddr_in clientAddress;
int clientAddressSize = sizeof(clientAddress);
SOCKET clientSocket = accept(serverSocket, reinterpret_cast<SOCKADDR*>(&clientAddress), &clientAddressSize);
if (clientSocket != INVALID_SOCKET)
{
std::thread clientThread(HandleClientCommunication, clientSocket);
clientThread.detach(); // 分离线程,不等待线程结束
}
}
Cleanup(serverSocket);
return 0;
}
3.客户端
Client.cpp
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#define PORT 65432
void Cleanup(SOCKET socket)
{
closesocket(socket);
WSACleanup();
}
int main()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
std::cout << "加载winsock.dll失败!" << std::endl;
return 0;
}
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET)
{
std::cout << "创建套接字失败!错误代码:" << WSAGetLastError() << std::endl;
Cleanup(clientSocket);
return 0;
}
sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &serverAddress.sin_addr);
if (connect(clientSocket, reinterpret_cast<SOCKADDR*>(&serverAddress), sizeof(serverAddress)) == SOCKET_ERROR)
{
std::cout << "连接失败!错误代码:" << WSAGetLastError() << std::endl;
Cleanup(clientSocket);
return 0;
}
while (true)
{
std::string receivedMessage;
char buffer[1000];
int size = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
if (size <= 0)
{
if (size == 0)
std::cout << "连接已关闭" << std::endl;
else
std::cout << "接收信息失败!错误代码:" << WSAGetLastError() << std::endl;
break;
}
buffer[size] = '\0';
receivedMessage = buffer;
if (receivedMessage == "end")
{
std::cout << "服务器端已关闭连接!" << std::endl;
break;
}
else
{
std::cout << "收到服务器消息:" << receivedMessage << std::endl;
}
std::string sendMessage;
std::cout << "请输入要发送给服务器的消息:" << std::endl;
std::getline(std::cin, sendMessage);
if (sendMessage == "end")
{
std::cout << "关闭连接!" << std::endl;
break;
}
int sentBytes = send(clientSocket, sendMessage.c_str(), static_cast<int>(sendMessage.length()), 0);
if (sentBytes == SOCKET_ERROR || sentBytes == 0)
{
std::cout << "[发送信息失败] 错误代码:" << WSAGetLastError() << std::endl;
break;
}
else
{
std::cout << " [信息发送成功]" << std::endl;
}
}
Cleanup(clientSocket);
return 0;
}
取消SDL检查()
右键ClientSocket项目->属性
C/C++->常规->SDL检查->点击下拉列表->选否
再点确定,退出
(使用一些c++中目前版本不太支持的语句时,sdl检查就会报错)
4.编译
f5运行或者点开始调试
项目->在资源管理打开文件夹
找到Debug文件夹,有的会发现只生成了客户端或者服务器的一个.exe文件
这时候说明只编译了一个,另一个没有编译
右键没有编译的项目->设为启动项
f5再编译一次,打开上面的Debug文件夹,就会发现都有了
这时候要打开两个终端运行,复制前面Debug的路径
win+R 输入cmd打开命令窗口
cd Debug的路径(粘贴刚才复制的路径)
ServerSocket.exe
再打开一个终端
cd Debug的路径(粘贴刚才复制的路径)
ClientSocket.exe
两边成功通信,建立连接