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

【linux网络编程】套接字socket

Linux 套接字(Socket)详细介绍

1. 什么是套接字(Socket)?

套接字(Socket) 是计算机网络通信的编程接口(API),它允许不同计算机或同一计算机上的进程通过 TCP/IP 网络进行数据交换。

  • 本质:一个用于 进程间通信(IPC) 的端点,是应用程序访问网络的接口,用于在不同计算机或同一计算机的进程之间通信。

  • 作用:在应用程序和网络协议之间建立连接,允许数据收发。

  • 特点

    • 支持本机和远程通信(同一主机进程通信或不同主机进程通信)。
    • 屏蔽底层网络传输细节(应用程序不需要直接操作 TCP/IP 数据包)。
    • 支持 TCP/UDP 通信(可靠的 TCP 或无连接的 UDP)。
    • 支持多种协议族(IPv4、IPv6、本地通信)。

📌 套接字的地位

  • 不属于传输层,而是应用程序访问传输层(TCP/UDP)的接口
  • 允许应用程序调用 TCP/UDP 来实现可靠或无连接的数据传输

2. 套接字的基本工作原理

网络通信流程

  1. 客户端创建套接字,请求连接服务器。
  2. 服务器创建套接字,等待客户端连接。
  3. 服务器接受连接,建立数据通道。
  4. 双方进行数据收发
  5. 连接关闭

一个完整的 TCP 连接:

客户端(192.168.1.10:50000)   →  服务器(192.168.1.100:80)
请求数据                       ←  响应数据

UDP 连接(无连接):

客户端(192.168.1.10:50000)  →  服务器(192.168.1.100:53)
DNS 查询                      ←  DNS 响应

3. 套接字的基本类型

1️⃣ 按通信方式分类

套接字类型说明典型协议
流式套接字(SOCK_STREAM)面向连接,可靠,有流量控制TCP
数据报套接字(SOCK_DGRAM)无连接,不可靠,速度快UDP
原始套接字(SOCK_RAW)直接访问 IP 层,常用于网络分析ICMP、ARP

2️⃣ 按协议族分类

地址族说明适用范围
AF_INETIPv4 套接字互联网通信
AF_INET6IPv6 套接字互联网通信
AF_UNIX本地进程间通信(IPC)本机进程通信
AF_PACKET直接访问底层数据链路层抓包、ARP

4. 套接字编程 API

📌 套接字 API 主要函数(C 语言)

函数作用
socket()创建套接字
bind()绑定 IP 和端口
listen()监听连接(TCP 服务器端)
accept()接受客户端连接
connect()连接服务器(TCP 客户端)
send()/recv()TCP 发送/接收数据
sendto()/recvfrom()UDP 发送/接收数据
close()关闭套接字

5. TCP 套接字通信示例

📌 服务器端(TCP)

#include <winsock2.h>
#include <iostream>

#pragma comment(lib, "ws2_32.lib")  // 链接 Winsock 库

#define PORT 8080
#define BUFFER_SIZE 1024

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

    // 2. 创建 Socket
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == INVALID_SOCKET) {
        std::cerr << "Socket 创建失败" << std::endl;
        WSACleanup();
        return 1;
    }

    // 3. 绑定地址
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);

    if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        std::cerr << "绑定失败" << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }

    // 4. 监听连接
    if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) {
        std::cerr << "监听失败" << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }
    std::cout << "服务器正在监听端口 " << PORT << "..." << std::endl;

    // 5. 接受客户端连接
    sockaddr_in clientAddr;
    int clientAddrSize = sizeof(clientAddr);
    SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrSize);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "接受连接失败" << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }
    std::cout << "客户端连接成功!" << std::endl;

    // 6. 接收数据
    char buffer[BUFFER_SIZE] = { 0 };
    int bytesReceived = recv(clientSocket, buffer, BUFFER_SIZE, 0);
    if (bytesReceived > 0) {
        std::cout << "收到客户端消息: " << buffer << std::endl;
    }

    // 7. 发送响应
    const char* response = "Hello from server!";
    send(clientSocket, response, strlen(response), 0);

    // 8. 关闭 Socket
    closesocket(clientSocket);
    closesocket(serverSocket);
    WSACleanup();

    return 0;
}


📌 客户端(TCP)

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>

#pragma comment(lib, "ws2_32.lib")  // 链接 Winsock 库

#define SERVER_IP "127.0.0.1"
#define PORT 8080
#define BUFFER_SIZE 1024

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

    // 2. 创建 Socket
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "Socket 创建失败" << std::endl;
        WSACleanup();
        return 1;
    }

    // 3. 连接服务器
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    //serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
    if (inet_pton(AF_INET, SERVER_IP, &serverAddr.sin_addr) <= 0) {
        std::cerr << "地址转换失败\n";
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }

    if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        std::cerr << "连接服务器失败" << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }
    std::cout << "成功连接到服务器!" << std::endl;

    // 4. 发送数据
    const char* message = "Hello from client!";
    send(clientSocket, message, strlen(message), 0);

    // 5. 接收服务器响应
    char buffer[BUFFER_SIZE] = { 0 };
    int bytesReceived = recv(clientSocket, buffer, BUFFER_SIZE, 0);
    if (bytesReceived > 0) {
        std::cout << "收到服务器消息: " << buffer << std::endl;
    }

    // 6. 关闭 Socket
    closesocket(clientSocket);
    WSACleanup();

    return 0;
}


6. UDP 套接字通信

UDP 没有连接过程,数据直接发送:

  • sendto() 发送数据
  • recvfrom() 接收数据

7. 套接字通信流程

📌 TCP(面向连接)

  1. 服务器

    • socket() 创建套接字
    • bind() 绑定端口
    • listen() 监听端口
    • accept() 等待连接
    • recv()/send() 进行通信
    • close() 关闭连接
  2. 客户端

    • socket() 创建套接字
    • connect() 连接服务器
    • send()/recv() 进行通信
    • close() 关闭连接

📌 UDP(无连接)

  1. 服务器

    • socket() 创建套接字
    • bind() 绑定端口
    • recvfrom()/sendto() 接收/发送数据
    • close() 关闭
  2. 客户端

    • socket() 创建套接字
    • sendto() 发送数据
    • recvfrom() 接收数据
    • close() 关闭

8. 总结

  1. 套接字是应用程序访问网络的 API,不属于传输层
  2. TCP 使用 SOCK_STREAM,UDP 使用 SOCK_DGRAM
  3. 客户端通常使用动态端口,服务器使用固定端口
  4. socket() 是网络编程的入口,应用程序通过它访问 TCP/UDP

📌 如果你想用 C 语言或 Python 进行网络编程,理解 socket 是最关键的一步! 🚀


http://www.kler.cn/a/577000.html

相关文章:

  • 迷宫【BFS+结构体\pair】
  • 力扣每日一题——2597. 美丽子集的数目
  • HarmonyOS Next 属性动画和转场动画
  • 【算法 C/C++】一维前缀和
  • 面试过了,总结测试工程师面试题(含答案)
  • Github 2025-03-08Rust开源项目日报Top10
  • 【JAVA架构师成长之路】【Redis】第15集:Redis大Key问题分析与解决方案
  • FPGA学习篇——Verilog学习5(reg,wire区分及模块例化)
  • 大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
  • AORO P9000 PRO三防平板携手RTK高精度定位,电力巡检效率倍增
  • ShardingSphere 和 Spring 的动态数据源切换机制的对比以及原理
  • 解决电脑问题(5)——鼠标问题
  • 后门攻击仓库 backdoor attack
  • 计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)
  • 基于Asp.net的驾校管理系统
  • Windows 远程桌面多端口访问,局域网虚拟IP映射多个Windows 主机解决方案
  • 使用 Docker 部署 Nginx,配置后端 API 轮询与多个子域名前端应用
  • RHCE9.0版本笔记4:聚焦网络安全基础技术
  • 头歌作业-mysql数据库系统(全部)
  • 【Json RPC框架】框架介绍与环境搭建(Ubuntu 22.04)