Socket编程实验


听学弟学妹们反馈,好像老师发的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;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泉绮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值