Socket编程实验

ops/2024/9/25 0:55:49/

文章目录

      • 服务端:
      • 客户端:
      • 使用说明:
      • 封装后服务端:
      • 封装后客户端

听学弟学妹们反馈,好像老师发的socket编程实验指导里的代码跑不起来。
今天花了一大把时间写了下socket编程代码
现在附上能跑的c++代码:
最重要的是,记得更改其中注释和变量名,不然的话容易被老师查重,一定要改
(后面有使用说明!)

服务端:

#include <iostream>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")
int main() {// 初始化 WinsockWSADATA wsaData;int result = WSAStartup(MAKEWORD(2, 2), &wsaData);if (result != 0) {std::cerr << "WSAStartup failed with error: " << result << std::endl;return 1;}// 创建 SocketSOCKET 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;}}// 关闭 Socketclosesocket(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() {// 初始化 WinsockWSADATA wsaData;int result = WSAStartup(MAKEWORD(2, 2), &wsaData);if (result != 0) {std::cerr << "WSAStartup failed with error: " << result << std::endl;return 1;}// 创建 SocketSOCKET 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;// 关闭 Socketclosesocket(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(); //先初始化WinsockcreateServerSocket();   //创建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://初始化Winsockint 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();}//设置目标IPint 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);   //设置ipclient->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;
}

http://www.ppmy.cn/ops/15471.html

相关文章

应用层协议 -- HTTPS 协议

目录 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 2、理解“加密” 二、对称加密 1、理解对称加密 2、对称加密存在的问题 三、非对称加密 1、理解非对称加密 2、中间人攻击 3、CA 证书和数字签名 四、总结 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 HTTPS 也是…

图像修复技术在AI去衣中的深度应用与探索

随着人工智能技术的飞速发展&#xff0c;图像修复技术在AI去衣领域的应用日益广泛。本文旨在深入探讨图像修复技术在AI去衣中的核心作用&#xff0c;并介绍一些专业的技术名词及其深刻解释。 一、引言 图像修复技术作为计算机视觉领域的重要分支&#xff0c;旨在通过算法对图…

Stream流对list<map>的操作

Map<String,Object> map new HashMap<>();map.put("name","张三");map.put("age","30");map.put("sex","男");map.put("addr","深圳");List<Map<String,Object>> l…

jmeter5.4.1源码编译(IDEA)问题解决

问题现象&#xff1a;最近想更深入的研究下jmeter5.4.1的原理及功能具体实现&#xff0c;从官网down了个源码&#xff0c;在本地使用IDEA工具导入项目、编译时&#xff0c;报以下错误&#xff1a; class jdk.internal.loader.ClassLoaders$PlatformClassLoader cannot be cast…

Process in Semiconductor(半导体工艺)

Front-End Process in Semiconductor 引言正文Front-endBack-endFront-end of lineProcess flowBack-end of lineSiN seal layerCVDLPCVDPECVDSOI PSVSOI ACTSOI PSV+引言

redis中的缓存穿透问题

缓存穿透 缓存穿透问题&#xff1a; 一般请求来到后端&#xff0c;都是先从缓存中查找数据&#xff0c;如果缓存中找不到&#xff0c;才会去数据库中查询数据。 而缓存穿透就是基于这一点&#xff0c;不断发送请求查询不存在的数据&#xff0c;从而使数据库压力过大&#xff…

Linux打开html

在 Linux 系统中&#xff0c;您可以使用默认的 Web 浏览器打开 HTML 文件。一般来说&#xff0c;您可以采用以下两种方式打开 HTML 文件&#xff1a; 使用终端命令行打开 HTML 文件 打开终端并进入到 HTML 文件所在目录&#xff0c;然后输入以下命令&#xff1a; xdg-open f…

在线Latex公式编辑网站

在线LaTeX公式编辑器-编辑器 (latexlive.com) LaTeX&#xff08;常被读作/ˈlɑːtɛk/或/ˈleɪtɛk/&#xff0c;正确读音:/ˈlɑːtɛx/音译&#xff1a;拉泰赫&#xff0c;写作 $\LaTeX$&#xff09;&#xff0c;是一种基于TeX的排版系统&#xff0c;由美国计算机科学家莱斯…