文章目录
- 服务端:
- 客户端:
- 使用说明:
- 封装后服务端:
- 封装后客户端
听学弟学妹们反馈,好像老师发的socket编程实验指导里的代码跑不起来。
今天花了一大把时间写了下socket编程代码
现在附上能跑的c++代码:
最重要的是,记得更改其中注释和变量名,不然的话容易被老师查重,一定要改
(后面有使用说明!)
服务端:
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
// 初始化 Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup failed with error: " << result << std::endl;
return 1;
}
// 创建 Socket
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}
// 绑定端口
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(8080);
result = bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (result == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
// 监听连接
result = listen(serverSocket, SOMAXCONN);
if (result == SOCKET_ERROR) {
std::cerr << "listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Server is listening on port 8080..." << std::endl;
// 接受客户端连接
SOCKET clientSocket = accept(serverSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "accept failed with error: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Client connected." << std::endl;
while (true) {
// 接收客户端发送的数据并打印
char buffer[1024];
result = recv(clientSocket, buffer, sizeof(buffer), 0);
if (result > 0) {
buffer[result] = '\0';
std::cout << "收到消息: " << buffer << std::endl;
const char* feedback = "服务端已经收到消息";
int result2 = send(clientSocket, feedback, strlen(feedback), 0);
if (result2 == SOCKET_ERROR) {
std::cerr << "返回消息报错 " << WSAGetLastError() << std::endl;
}
}
else if (result == 0) {
std::cout << "客户端已关闭." << std::endl;
break;
}
else {
std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
break;
}
}
// 关闭 Socket
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return 0;
}
客户端:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> // 包含 InetPton 函数的声明
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main() {
// 初始化 Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup failed with error: " << result << std::endl;
return 1;
}
// 创建 Socket
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}
// 连接到服务端
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // 将字符串转换为网络地址
serverAddr.sin_port = htons(8080); // 服务端端口
result = connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (result == SOCKET_ERROR) {
std::cerr << "connect failed with error: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
std::cout << "Connected to server." << std::endl;
std::cout << "已经成功链接到服务端" << std::endl;
// 输入消息并发送到服务端
std::cout << "请输入发送到服务端的信息 (发送 exit 则断开链接):" << std::endl;
std::string message;
while (true) {
std::getline(std::cin, message);
if (message == "exit") {
break;
}
result = send(clientSocket, message.c_str(), message.length(), 0);
if (result == SOCKET_ERROR) {
std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
// 接收服务端的反馈信息
char buffer[1024];
result = recv(clientSocket, buffer, sizeof(buffer), 0);
if (result > 0) {
buffer[result] = '\0';
std::cout << "发送成功: " << buffer << std::endl;
}
else if (result == 0) {
std::cout << "服务端连接关闭" << std::endl;
}
else {
std::cerr << "出错了: " << WSAGetLastError() << std::endl;
}
}
std::cout << "Message sent to server." << std::endl;
// 关闭 Socket
closesocket(clientSocket);
WSACleanup();
return 0;
}
使用说明:
1,这个程序得用visual studio来运行,就是这个:
2, 你要建2个项目
步骤:
(1)
(2)
(3)
(4)
(5)
重复以上(1)~(4)步骤
这样你就得到了两个项目,往这两个项目的cpp文件中分别复制粘贴服务端代码和客户端代码。
最后先运行服务端,再运行客户端
就可以把客户端信息发送到服务端了。
重要的是,记得更改其中注释和变量名,不然的话容易被老师查重
后面的代码就是我封装了以后的服务端与客户端。
服务端里使用了多线程进行处理信息,
客户端有连接设置,连不上会自动重连。
欢迎扩展,拿去改改当轮子用
封装后服务端:
#include <iostream>
#include <winsock2.h>
#include <thread>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
class MyServer {
public:
MyServer() {
init(); //先初始化Winsock
createServerSocket(); //创建Socket服务端
}
//设置端口
int setPort(int ppot) {
port = ppot;
return 0;
}
//创建套接字
int setServerBind() {
//在服务端创建一个套接字,并将其绑定到指定的 IP 地址和端口号上,以便服务端能够监听客户端的连接请求
serverAddr.sin_family = AF_INET; //设置地址族为AF_INET.即IPv4地址
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); //将IP地址设置为INADDR_ANY 表示可以接收来自任何可用接口的连接请求
serverAddr.sin_port = htons(port); //设置端口号,表示服务端将在port端口上监听连接请求
//将服务端套接字绑定在指定地址上。
int result = bind(*serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (result == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
closesocket(*serverSocket);
WSACleanup();
return 1;
}
return 0;
}
//设置监听连接
int listenPost() {
// 监听连接
int result = listen(*serverSocket, SOMAXCONN);
if (result == SOCKET_ERROR) {
std::cerr << "listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(*serverSocket);
WSACleanup();
return 1;
}
std::cout << "服务端正在监视端口" << port << std::endl;
return 0;
}
//处理连接
int disposeConnect() {
while (true) {
SOCKET clientSocket = accept(*serverSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "出问题了: " << WSAGetLastError() << std::endl;
closesocket(*serverSocket);
WSACleanup();
return 1;
}
// 创建线程处理连接
std::thread clientThread(&MyServer::HandleClient, this, clientSocket);
clientThread.detach(); // 在后台运行线程,不阻塞主线程
}
return 0;
}
//关闭套接字
int closeServer() {
closesocket(*serverSocket);
WSACleanup();
return 0;
}
~MyServer() {
}
private:
//初始化Winsock
int init() {
std::cout << "正在初始化Winsock" << std::endl;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup运行失败,报错: " << result << std::endl;
return 1;
}
std::cout << "初始化成功" << std::endl;
return 0;
}
//创建Socket服务端
int createServerSocket() {
std::cout << "正在创建Socket服务端" << std::endl;
serverSocket = new SOCKET(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (*serverSocket == INVALID_SOCKET) {
// 判断是否创建成功
std::cerr << "socket服务端创建失败,报错: " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}
std::cout << "创建成功" << std::endl;
return 0;
}
//处理单个客户端连接
void HandleClient(SOCKET client) {
sockaddr_in clientAddr;
int addrLen = sizeof(clientAddr);
getpeername(client, (SOCKADDR*)&clientAddr, &addrLen);
char clientIP[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(clientAddr.sin_addr), clientIP, INET_ADDRSTRLEN);
std::cout << "来自" << clientIP << ":" << ntohs(clientAddr.sin_port) << "的连接" << std::endl;
while (true) {
char buffer[1024];
int result = recv(client, buffer, sizeof(buffer), 0);
if (result > 0) {
buffer[result] = '\0';
std::cout << clientIP << ":" << ntohs(clientAddr.sin_port) << ": " << buffer << std::endl;
const char* feedback = "Message received by server.";
int result2 = send(client, feedback, strlen(feedback), 0);
if (result2 == SOCKET_ERROR) {
std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
}
}
else if (result == 0) {
std::cout << clientIP << ":" << ntohs(clientAddr.sin_port) << ": ""连接关闭." << std::endl;
break;
}
else {
std::cerr << clientIP << ":" << ntohs(clientAddr.sin_port) << ": ""错误: " << WSAGetLastError() << std::endl;
break;
}
}
closesocket(client);
}
SOCKET* serverSocket; //Socket服务端
int port = 8080; // 端口号
sockaddr_in serverAddr; //服务端地址信息
WSADATA wsaData; //
};
int main() {
MyServer* server = new MyServer();
/*int pot;*/
/*std::cout << "请输入端口:";
std::cin >> pot;*/
server->setServerBind();
server->listenPost();
server->disposeConnect();
server->closeServer();
return 0;
}
封装后客户端
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> // 包含 InetPton 函数的声明
#include <string>
#include <thread>
#pragma comment(lib, "ws2_32.lib")
class MyClient {
public:
MyClient() {
init();
createClientSocket();
}
//设置目标IP
int setAimIp(char* ip) {
aimIp = ip;
return 0;
}
//设置目标端口
int setAimPort(int pot) {
aimPort = pot;
return 0;
}
//连接服务端
int ConnectServer() {
while (1) {
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
inet_pton(AF_INET, aimIp, &serverAddr.sin_addr); // 将字符串转换为网络地址
std::cout << "目标:" << aimIp << ":" << aimPort << std::endl;
serverAddr.sin_port = htons(aimPort); // 服务端端口
int result = connect(*clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (result == SOCKET_ERROR) {
std::cerr << "connect failed with error: " << WSAGetLastError() << std::endl;
std::cout << "Waiting for server to start..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5)); // 等待5秒
continue; // 继续尝试重新连接
}
std::cout << "已经成功链接到服务端" << aimIp << ":" << aimPort << std::endl;
break;
}
return 0;
}
//发送信息
int sendMessage(char* message) {
int result = send(*clientSocket, message, sizeof(message), 0);
if (result == SOCKET_ERROR) {
std::cerr << "发送失败: " << WSAGetLastError() << std::endl;
closesocket(*clientSocket);
WSACleanup();
return 1;
}
// 接收服务端的反馈信息
char buffer[1024];
result = recv(*clientSocket, buffer, sizeof(buffer), 0);
if (result > 0) {
buffer[result] = '\0';
std::cout << "发送成功: " << buffer << std::endl;
}
else if (result == 0) {
std::cout << "服务端连接关闭" << std::endl;
}
else {
std::cerr << "出错了: " << WSAGetLastError() << std::endl;
}
return 0;
}
//关闭客户端
int closeClient() {
closesocket(*clientSocket);
return 0;
}
~MyClient() {
WSACleanup();
}
private:
//初始化
int init() {
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup failed with error: " << result << std::endl;
return 1;
}
return 0;
}
//创建客户端
int createClientSocket() {
std::cout << "正在创建Socket客户端" << std::endl;
clientSocket = new SOCKET(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (*clientSocket == INVALID_SOCKET) {
std::cerr << "ocket客户端创建失败,报错:" << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}
std::cout << "创建成功" << std::endl;
return 0;
}
WSADATA wsaData;
SOCKET* clientSocket;
char* aimIp;
int aimPort;
};
int main() {
MyClient* client = new MyClient();
char ip[] = "127.0.0.1";
int port = 8080;
client->setAimIp(ip); //设置ip
client->setAimPort(port); //设置端口
client->ConnectServer();//连接服务器
// 输入消息并发送到服务端
std::cout << "请输入发送到服务端的信息 (发送 exit 则断开链接):" << std::endl;
char* message = new char[1024];
while (true) {
std::cin.getline(message, 1024);
if (!strcmp(message, "exit")) {
break;
}
client->sendMessage(message);
}
return 0;
}