C++ socket网络编程方法是什么

发布时间:2021-11-19 12:49:08 作者:iii
来源:亿速云 阅读:146
# C++ Socket网络编程方法是什么

## 1. Socket编程基础概念

Socket(套接字)是网络通信的基石,它允许不同主机或同一主机的不同进程之间进行数据交换。在C++中,我们通常使用Berkeley Socket API(BSD Socket)进行网络编程。

### 1.1 Socket类型
- **流式Socket(SOCK_STREAM)**:面向连接的TCP通信
- **数据报Socket(SOCK_DGRAM)**:无连接的UDP通信
- **原始Socket(SOCK_RAW)**:底层协议访问

### 1.2 基本通信流程

客户端:创建Socket -> 连接服务器 -> 发送/接收数据 -> 关闭连接 服务器:创建Socket -> 绑定地址 -> 监听连接 -> 接受连接 -> 发送/接收数据 -> 关闭连接


## 2. 核心API详解

### 2.1 基础函数

```cpp
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 创建socket
int socket(int domain, int type, int protocol);

// 绑定地址
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 监听连接
int listen(int sockfd, int backlog);

// 接受连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

// 建立连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 发送数据
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

// 接收数据
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

2.2 地址结构

// IPv4地址结构
struct sockaddr_in {
    sa_family_t    sin_family; // 地址族(AF_INET)
    in_port_t      sin_port;   // 端口号
    struct in_addr sin_addr;   // IP地址
};

// IPv6地址结构
struct sockaddr_in6 {
    sa_family_t     sin6_family; 
    in_port_t       sin6_port;
    uint32_t        sin6_flowinfo;
    struct in6_addr sin6_addr;
    uint32_t        sin6_scope_id;
};

3. TCP服务器实现示例

3.1 基本TCP服务器

#include <iostream>
#include <cstring>
#include <unistd.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    
    // 创建socket文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FLURE);
    }
    
    // 设置socket选项
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FLURE);
    }
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    
    // 绑定socket到端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FLURE);
    }
    
    // 开始监听
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FLURE);
    }
    
    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FLURE);
    }
    
    // 读取客户端数据
    read(new_socket, buffer, BUFFER_SIZE);
    printf("Client says: %s\n", buffer);
    
    // 发送响应
    const char *hello = "Hello from server";
    send(new_socket, hello, strlen(hello), 0);
    printf("Hello message sent\n");
    
    // 关闭连接
    close(new_socket);
    close(server_fd);
    return 0;
}

4. TCP客户端实现示例

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    const char *hello = "Hello from client";
    char buffer[1024] = {0};
    
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("\n Socket creation error \n");
        return -1;
    }
    
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    
    // 转换IP地址
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }
    
    // 连接服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("\nConnection Failed \n");
        return -1;
    }
    
    // 发送数据
    send(sock, hello, strlen(hello), 0);
    printf("Hello message sent\n");
    
    // 接收响应
    read(sock, buffer, 1024);
    printf("Server says: %s\n", buffer);
    
    close(sock);
    return 0;
}

5. UDP通信实现

5.1 UDP服务器

#include <iostream>
#include <cstring>
#include <arpa/inet.h>

#define PORT 8080
#define MAXLINE 1024

int main() {
    int sockfd;
    char buffer[MAXLINE];
    struct sockaddr_in servaddr, cliaddr;
    
    // 创建UDP socket
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FLURE);
    }
    
    memset(&servaddr, 0, sizeof(servaddr));
    memset(&cliaddr, 0, sizeof(cliaddr));
    
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);
    
    // 绑定socket
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind failed");
        exit(EXIT_FLURE);
    }
    
    socklen_t len;
    int n;
    
    len = sizeof(cliaddr);
    
    // 接收数据
    n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WTALL, 
                (struct sockaddr *)&cliaddr, &len);
    buffer[n] = '\0';
    printf("Client : %s\n", buffer);
    
    // 发送响应
    const char *hello = "Hello from server";
    sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM,
          (const struct sockaddr *)&cliaddr, len);
    printf("Hello message sent.\n");
    
    return 0;
}

6. 高级主题与最佳实践

6.1 多线程服务器

#include <thread>
#include <vector>

void handle_client(int client_socket) {
    char buffer[1024] = {0};
    read(client_socket, buffer, 1024);
    printf("Received: %s\n", buffer);
    
    const char *response = "Message received";
    send(client_socket, response, strlen(response), 0);
    close(client_socket);
}

int main() {
    // ... (服务器初始化代码同前)
    
    while (true) {
        int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            perror("accept");
            continue;
        }
        
        std::thread(handle_client, new_socket).detach();
    }
    
    close(server_fd);
    return 0;
}

6.2 错误处理建议

  1. 检查所有socket API调用的返回值
  2. 使用perror()输出错误信息
  3. 实现优雅的资源释放
  4. 考虑使用RI管理socket资源

7. 跨平台注意事项

  1. Windows需要WSAStartup()初始化
  2. Windows使用closesocket()而非close()
  3. 头文件差异:Windows使用
  4. 错误代码获取方式不同

8. 总结

C++ Socket编程是构建网络应用的基础,掌握TCP/UDP通信模型、理解socket API的使用方法,并遵循最佳实践,可以开发出高效可靠的网络应用程序。现代C++项目通常会使用更高级的网络库(如Boost.Asio)来简化开发,但理解底层socket工作原理仍然至关重要。 “`

这篇文章涵盖了C++ Socket编程的核心内容,包括: 1. 基础概念和通信流程 2. 关键API详解 3. TCP/UDP服务器和客户端实现 4. 多线程处理 5. 错误处理和跨平台注意事项

总字数约1350字,采用Markdown格式,包含代码示例和结构化内容。

推荐阅读:
  1. C++中Socket网络编程实例详解
  2. C++的socket封装方法是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++ socket

上一篇:SpringBoot框架配置文件路径设置方法是什么

下一篇:怎么用C语言给喜欢的人写烟花

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》