Windows C++ TCP/IP 两台电脑上互相传输字符串数据

在 Windows 上使用 C++ 实现两个进程通过 TCP/IP 协议传输字符串数据是一个非常常见的任务。我们可以利用 Windows Sockets API (winsock2) 来进行套接字编程。在下面的例子中,我们将演示如何通过 TCP/IP 协议传输字符串数据。这里将包括两个程序:一个是服务器端,另一个是客户端。

1. 环境准备

  1. 安装开发环境:
    • Visual Studio:确保你已经安装了 Visual Studio,且能够编译 C++ 程序。
    • 连接到 ws2_32.lib:如果你使用的是 Visual Studio,它默认包含了 Windows Sockets 库,无需额外配置。

2. 服务器端代码 (Server)

服务器端将监听特定端口,接受来自客户端的连接,并接收字符串数据。

cpp 复制代码
#include <iostream>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")  // Link with ws2_32.lib for Winsock

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    // 初始化 Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed!" << std::endl;
        return -1;
    }

    // 创建服务器套接字
    SOCKET server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == INVALID_SOCKET) {
        std::cerr << "Socket creation failed!" << std::endl;
        WSACleanup();
        return -1;
    }

    // 设置服务器地址
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;  // 监听所有接口
    server_addr.sin_port = htons(PORT);

    // 绑定套接字到端口
    if (bind(server_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
        std::cerr << "Bind failed!" << std::endl;
        closesocket(server_socket);
        WSACleanup();
        return -1;
    }

    // 开始监听客户端请求
    if (listen(server_socket, 1) == SOCKET_ERROR) {
        std::cerr << "Listen failed!" << std::endl;
        closesocket(server_socket);
        WSACleanup();
        return -1;
    }

    std::cout << "Server listening on port " << PORT << "..." << std::endl;

    // 接受客户端连接
    SOCKET client_socket = accept(server_socket, NULL, NULL);
    if (client_socket == INVALID_SOCKET) {
        std::cerr << "Accept failed!" << std::endl;
        closesocket(server_socket);
        WSACleanup();
        return -1;
    }

    std::cout << "Client connected!" << std::endl;

    // 接收字符串数据
    char buffer[BUFFER_SIZE];
    int bytes_received;
    while (true) {
        bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
        if (bytes_received <= 0) {
            break;  // 连接关闭或发生错误
        }
        buffer[bytes_received] = '\0';  // 添加字符串结束符
        std::cout << "Received: " << buffer << std::endl;
    }

    // 清理资源
    closesocket(client_socket);
    closesocket(server_socket);
    WSACleanup();

    return 0;
}

3. 客户端代码 (Client)

客户端将连接到服务器并发送字符串数据。

cpp 复制代码
#include <iostream>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")  // Link with ws2_32.lib for Winsock

#define SERVER_IP "192.168.10.10"  // 服务器
#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    // 初始化 Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed!" << std::endl;
        return -1;
    }

    // 创建客户端套接字
    SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket == INVALID_SOCKET) {
        std::cerr << "Socket creation failed!" << std::endl;
        WSACleanup();
        return -1;
    }

    // 设置服务器地址
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    // 连接到服务器
    if (connect(client_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
        std::cerr << "Connect failed!" << std::endl;
        closesocket(client_socket);
        WSACleanup();
        return -1;
    }

    std::cout << "Connected to server!" << std::endl;

    // 发送字符串数据
    const char* message = "Hello, Server! This is the client.";
    int bytes_sent = send(client_socket, message, strlen(message), 0);
    if (bytes_sent == SOCKET_ERROR) {
        std::cerr << "Send failed!" << std::endl;
        closesocket(client_socket);
        WSACleanup();
        return -1;
    }

    std::cout << "Message sent to server!" << std::endl;

    // 清理资源
    closesocket(client_socket);
    WSACleanup();

    return 0;
}

4. 编译和运行

步骤 1:编译代码

  1. 打开 Visual Studio,创建两个 C++ 控制台应用程序:一个用于服务器端,另一个用于客户端。
  2. 需要链接 ws2_32.lib 库,它是 Winsock2 的实现库。在 Visual Studio 中,可以在项目设置中配置链接器输入,添加 ws2_32.lib

步骤 2:运行服务器端

  1. 在命令行中运行服务器程序 server.exe,它将监听端口 8080,等待客户端连接。

    bash 复制代码
    server.exe

步骤 3:运行客户端

  1. 在另一个命令行窗口中运行客户端程序 client.exe,客户端将连接到服务器并发送消息。

    bash 复制代码
    client.exe

步骤 4:查看输出

  • 服务器端:会打印接收到的消息:

    bash 复制代码
    Received: Hello, Server! This is the client.
  • 客户端:会显示发送的消息确认:

    bash 复制代码
    Message sent to server!

5. 代码解释

  1. Winsock 初始化和清理 :通过 WSAStartup 初始化 Windows 套接字,WSACleanup 清理资源。
  2. 套接字创建和连接:
    • 服务器端 :创建一个 TCP 套接字,绑定到本地端口 8080,并开始监听客户端的连接。
    • 客户端:创建一个套接字并连接到服务器的 IP 地址和端口。
  3. 数据发送和接收:
    • 客户端通过 send() 发送一个字符串消息。
    • 服务器通过 recv() 接收消息并打印出来。
  4. 字符串处理 :服务器端接收的字符串会加上 \0 字符来确保它是一个有效的 C 字符串。

6. 小结

这个示例展示了如何使用 TCP/IP 协议传输字符串数据:

  • 服务器端等待客户端的连接,并接收来自客户端的字符串消息。
  • 客户端连接到服务器,并发送字符串消息。
  • 通过 winsock2 库进行套接字编程,确保数据的传输是可靠的。

你可以根据实际需求修改和扩展这个基础代码,例如:

  • 增加错误处理(例如,处理数据发送或接收失败的情况)。
  • 支持多客户端连接(通过 select()multithreading)。
  • 在客户端和服务器之间实现更复杂的协议。
相关推荐
量子炒饭大师14 分钟前
【C++入门】Cyber底码作用域的隔离协议——【C++命名空间】(using namespace std的原理)
开发语言·c++·dubbo
逐梦苍穹30 分钟前
不用公网 IP,把内网服务安全发布到公网:ZeroNews 快速上手
网络协议·tcp/ip·安全·内网穿透
REDcker34 分钟前
RTCP 刀尖点跟随技术详解
c++·机器人·操作系统·嵌入式·c·数控·机床
楚Y6同学35 分钟前
基于 Haversine 公式实现【经纬度坐标点】球面距离计算(C++/Qt 实现)
开发语言·c++·qt·经纬度距离计算
子琦啊1 小时前
WIN11电脑桌面“固定到开始”菜单失效解决办法
windows·电脑
老歌老听老掉牙1 小时前
优化样条曲线拟合参数解决三维建模中的截面连续性问题
c++·opencascade·样条曲线
散峰而望2 小时前
【算法竞赛】栈和 stack
开发语言·数据结构·c++·算法·leetcode·github·推荐算法
jjjddfvv2 小时前
超级简单启动llamafactory!
windows·python·深度学习·神经网络·微调·audiolm·llamafactory
不爱吃糖的程序媛2 小时前
OpenHarmony 通用C/C++三方库 标准化鸿蒙化适配
c语言·c++·harmonyos
fqbqrr2 小时前
2601C++,导出控制
c++