【C++】套接字(socket)

在C++中,使用套接字(socket)进行网络编程涉及到创建、绑定、监听、连接和数据传输等操作。以下是详细介绍和示例代码,说明如何在C++中使用套接字进行网络编程。通常,使用的头文件是 <sys/socket.h><arpa/inet.h> 等。这些头文件在大多数Unix-like系统(包括Linux和macOS)上都可以找到。Windows系统上需要使用 <winsock2.h> 头文件,并进行一些特定的初始化操作。

基本步骤

  1. 创建套接字:使用 socket() 函数。
  2. 绑定套接字:使用 bind() 函数。
  3. 监听连接(服务器端):使用 listen() 函数。
  4. 接受连接(服务器端):使用 accept() 函数。
  5. 连接到服务器(客户端):使用 connect() 函数。
  6. 发送和接收数据:使用 send()recv() 函数。

示例代码

以下是一个简单的服务器和客户端示例代码。

服务器代码
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>

#define PORT 8080

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};

    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 绑定套接字
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 接收数据
    int valread = read(new_socket, buffer, 1024);
    std::cout << "Received: " << buffer << std::endl;

    // 发送数据
    const char *response = "Hello from server";
    send(new_socket, response, strlen(response), 0);
    std::cout << "Response sent" << std::endl;

    // 关闭套接字
    close(new_socket);
    close(server_fd);

    return 0;
}
客户端代码
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>

#define PORT 8080

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[1024] = {0};

    // 创建套接字
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        std::cerr << "Socket creation error" << std::endl;
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 将地址转换成二进制格式
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        std::cerr << "Invalid address/ Address not supported" << std::endl;
        return -1;
    }

    // 连接到服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "Connection Failed" << std::endl;
        return -1;
    }

    // 发送数据
    const char *message = "Hello from client";
    send(sock, message, strlen(message), 0);
    std::cout << "Message sent" << std::endl;

    // 接收数据
    int valread = read(sock, buffer, 1024);
    std::cout << "Received: " << buffer << std::endl;

    // 关闭套接字
    close(sock);

    return 0;
}

详细说明

  1. 创建套接字

    • 使用 socket() 函数创建套接字,AF_INET 表示使用IPv4协议,SOCK_STREAM 表示使用TCP协议。
  2. 绑定套接字

    • 使用 bind() 函数将套接字绑定到指定的IP地址和端口。INADDR_ANY 允许接收所有网卡的连接。
  3. 监听连接

    • 使用 listen() 函数将套接字设置为监听模式,等待客户端连接。
  4. 接受连接

    • 使用 accept() 函数从已连接队列中提取第一个连接请求,返回一个新的套接字,用于与客户端通信。
  5. 连接到服务器

    • 客户端使用 connect() 函数连接到服务器。
  6. 发送和接收数据

    • 使用 send()recv() 函数在套接字之间发送和接收数据。

注意事项

  • 在实际开发中,错误处理非常重要。应当在每个系统调用后检查返回值,并进行适当的错误处理。
  • 套接字编程涉及到网络编程中的许多细节和复杂性,如网络字节序、非阻塞I/O、多线程等。实际应用中可能需要使用更高级的库(如Boost.Asio)来简化开发。

这样,使用C++的套接字编程可以有效地进行网络通信,实现客户端和服务器的交互。

C++中的socket套接字编程是一种让程序能够进行网络通信的方式。以下是使用C++进行TCP套接字编程的一个简单示例,分别展示了服务器端和客户端的代码。 服务器端示例代码: ```cpp #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; const char *greeting = "Hello from server"; // 创建socket文件描述符 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 绑定socket到地址和端口 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听socket if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接受来自客户端的连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 读取客户端发送的数据 read(new_socket, buffer, 1024); std::cout << "Message from client: " << buffer << std::endl; // 向客户端发送数据 send(new_socket, greeting, strlen(greeting), 0); std::cout << "Greeting message sent\n"; // 关闭socket close(server_fd); return 0; } ``` 客户端示例代码: ```cpp #include <iostream> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> int main() { int sock = 0; struct sockaddr_in serv_addr; const char *hello = "Hello from client"; char buffer[1024] = {0}; // 创建socket文件描述符 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { std::cout << "\n Socket creation error \n"; return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(8080); // 将IPv4和IPv6地址从文本转换为二进制形式 if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { std::cout << "\nInvalid address/ Address not supported \n"; return -1; } // 连接到服务器 if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { std::cout << "\nConnection Failed \n"; return -1; } // 发送数据到服务器 send(sock, hello, strlen(hello), 0); std::cout << "Hello message sent\n"; // 读取服务器的响应 read(sock, buffer, 1024); std::cout << "Message from server: " << buffer << std::endl; // 关闭socket close(sock); return 0; } ``` 在上述示例中,服务器端创建了一个socket并监听在8080端口上,当客户端连接时,服务器读取客户端发送的消息,然后发送一个问候消息,并关闭连接。客户端连接到服务器,发送一条消息,然后接收服务器的响应,最后关闭连接。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值