当前位置: 首页 > news >正文

socket描述符的本质,它可以和服务器建立连接?一个服务器和一个客户端的通信中,三个操作符的作用分别是什么?

 描述符的本质

    socket 描述符(在类 Unix 系统中是一个非负整数,在 Windows 系统中是 SOCKET 句柄)本质上是操作系统为了管理网络连接而分配的一个索引值,它用于标识一个打开的网络套接字,方便后续对该套接字进行读写、关闭等操作。
    socket 描述符(socket descriptor)是可以用于和服务器建立连接的。

 

客户端的 socket 描述符

在客户端,通常会使用一个 socket 描述符来完成与服务器的连接和通信,其创建和使用过程如下:

1. 创建 socket 描述符

客户端首先使用 socket 函数创建一个 socket 描述符,这个描述符代表了客户端用于网络通信的端点。示例代码如下:

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 8888
#define SERVER_IP "127.0.0.1"

int main() {
    int client_socket;
    // 创建客户端 socket 描述符
    client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket == -1) {
        perror("socket creation failed");
        return -1;
    }
    // 后续代码...
    close(client_socket);
    return 0;
}

这里 client_socket 就是客户端创建的 socket 描述符,AF_INET 表示使用 IPv4 地址族,SOCK_STREAM 表示使用面向连接的 TCP 协议。

2. 连接到服务器

客户端使用 connect 函数,通过这个 socket 描述符向服务器发起连接请求:

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("Invalid address/ Address not supported");
        return -1;
    }
    if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connection failed");
        close(client_socket);
        return -1;
    }

此时,客户端的 client_socket 描述符就与服务器建立了连接,可以用于后续的数据收发。

3. 数据收发和关闭连接

客户端可以使用 send 和 recv 函数通过 client_socket 描述符进行数据的发送和接收,通信结束后使用 close 函数关闭该描述符:

    char message[] = "Hello, server!";
    if (send(client_socket, message, sizeof(message), 0) == -1) {
        perror("send failed");
        close(client_socket);
        return -1;
    }
    char buffer[1024];
    ssize_t bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
    if (bytes_received == -1) {
        perror("recv failed");
        close(client_socket);
        return -1;
    }
    close(client_socket);

服务器端的 socket 描述符

在服务器端,通常会使用至少两个 socket 描述符来完成与客户端的通信,分别是监听 socket 描述符和连接 socket 描述符。

1. 监听 socket 描述符

服务器首先创建一个监听 socket 描述符,用于监听客户端的连接请求:

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 8888
#define BACKLOG 5

int main() {
    int listen_socket;
    // 创建监听 socket 描述符
    listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket == -1) {
        perror("socket creation failed");
        return -1;
    }
    struct 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(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind failed");
        close(listen_socket);
        return -1;
    }
    // 开始监听
    if (listen(listen_socket, BACKLOG) == -1) {
        perror("listen failed");
        close(listen_socket);
        return -1;
    }
    // 后续代码...
    close(listen_socket);
    return 0;
}

这里的 listen_socket 就是监听 socket 描述符,它的作用是绑定服务器的地址和端口,并开始监听客户端的连接请求。BACKLOG 表示连接请求队列的最大长度。

2. 连接 socket 描述符

当有客户端发起连接请求时,服务器使用 accept 函数从监听队列中取出一个连接请求,并创建一个新的连接 socket 描述符来与该客户端进行通信:

    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int client_socket;
    // 接受客户端连接
    client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &client_addr_len);
    if (client_socket == -1) {
        perror("accept failed");
        close(listen_socket);
        return -1;
    }
    // 后续代码...
    close(client_socket);

client_socket 就是连接 socket 描述符,它代表了服务器与特定客户端之间的连接。服务器可以使用 send 和 recv 函数通过这个描述符与客户端进行数据的收发。

  • 客户端的 socket 描述符:用于创建与服务器的连接,以及后续与服务器之间的数据收发和关闭连接操作。
  • 服务器的监听 socket 描述符:用于绑定服务器的地址和端口,监听客户端的连接请求。
  • 服务器的连接 socket 描述符:当有客户端连接请求到达时,服务器创建该描述符来与特定客户端进行一对一的数据通信。

相关文章:

  • 【基于C#实现Bartender多条码打印的示例】
  • uniapp开通开屏广告后动态开启或关闭开屏广告
  • Spring Boot项目打包第三方Jar包
  • 【JavaEE】多线程进阶(2)
  • 网络安全工具nc(NetCat)
  • 【Linux跬步积累】—— 网络编程套接字
  • Python毕业设计选题:基于django+vue的疫情数据可视化分析系统
  • java-算法基础优化
  • FreeSWITCH 之 chat
  • 脏读、不可重复读,幻读的区别 mvcc及四种隔离级别
  • 2025年3家大牌云电脑游戏、AIGC大PK,最低0.1元,配置不再是问题
  • ⭐LeetCode(数学分类) 48. 旋转图像——优美的数学法转圈(原地修改)⭐
  • 《领导力21法则》第三章「过程法则」笔记
  • Sentinel-1 InSAR ISCE数据处理:stackSentinel.py 完全指南
  • 考研数学复习之拉格朗日中值定理求解函数极限
  • 深入链表操作:C语言中的链表中间节点查找与合并
  • 《Android 平台架构系统启动流程详解》
  • sparkTTS window 安装
  • MFC 项目:简易销售系统实践
  • MoonSharp 文档四
  • 中国代表:美国才是南海安全稳定的最大威胁
  • 2025年上海市工程建设标准国际化工作要点发布
  • 错过航班大闹机场女子发声:非母子关系,将起诉视频发布者
  • 牛市早报|央行:加力支持提振消费、稳定外贸等领域,用好用足存量增量政策
  • 国家统计局督察组:江苏有关地区仍存在干预数据上报等问题
  • 德国放弃长期以来的反核立场,寻求修复德法合作关系