Linux Socket 编程

一、 Socket 概述

Socket 是一种用于在不同进程间进行网络通信的机制,也是 Linux 下网络编程的基础,也就是说在 Linux 下进行网络通信主要就是使用 Socket。

其中 Socket 可以描述成是文件描述符,它是一个整数,就像文件描述符一样可以使用 read、write、close 等函数对它进行操作。Socket 可以分为两种类型:流式 Socket 和数据报式 Socket。

二、网络编程基础 API

下面先列举一些 Network编程基础 API:

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

    //命名 Socket
    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    //将未连接的 Socket 转换为连接的 Socket
    int listen(int sockfd, int backlog);

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

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

    //建立连接请求的服务端
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    //发起连接请求的客户端
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    // 关闭 Socket
    int close(int sockfd);

三、流式 Socket

流式 Socket 是由 TCP 协议提供服务的,主要用于可靠的、有序的、基于连接的数据传输,特点如下:

1.面向连接;

2.提供可靠的数据传输;

3.通过三次握手连接,确保连接的建立;

4.数据是按顺序传输的,不存在数据丢失、重复等问题。

3.1 服务端实现

    // 创建 Socket
    int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 命名 Socket
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET; // 地址族
    server_address.sin_port = htons(12345); // 端口号
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); // IP 地址,INADDR_ANY 表示可以接收任何地址
    bind(server_sockfd, (struct sockaddr *)&server_address, sizeof(server_address));

    // 将未连接的 Socket 转换为连接的 Socket
    listen(server_sockfd, 5);

    // 服务端等待客户端的连接请求
    int client_sockfd;
    struct sockaddr_in client_address;
    socklen_t client_len = sizeof(client_address);
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

    // 向客户端发送数据
    char message[] = "Hello, client!";
    write(client_sockfd, message, sizeof(message));

    // 关闭 Socket
    close(client_sockfd);
    close(server_sockfd);

3.2 客户端实现

    // 创建 Socket
    int client_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 向服务端发起连接请求
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET; // 地址族
    server_address.sin_port = htons(12345); // 端口号
    server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
    connect(client_sockfd, (struct sockaddr*)&server_address, sizeof(server_address));

    // 从服务端接收数据
    char message[1024];
    read(client_sockfd, message, sizeof(message));
    printf("Message from server: %s\n", message);

    // 关闭 Socket
    close(client_sockfd);

四、数据报式 Socket

数据报式 Socket 是由 UDP 协议提供服务的,主要用于无连接、不可靠、允许数据失去和重复等问题的数据传输,特点如下:

1.无连接;

2.数据传输不可靠;

3.没有三次握手连接,也无需维护连接状态;

4.数据传输可能丢失、重复等问题。

4.1 服务端实现

    // 创建 Socket
    int server_sockfd;
    server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 命名 Socket
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET; // 地址族
    server_address.sin_port = htons(12345); // 端口号
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); // IP 地址,INADDR_ANY 表示可以接收任何地址
    bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address));

    // 接收客户端发送的数据
    char message[1024];
    struct sockaddr_in client_address;
    socklen_t client_len = sizeof(client_address);
    recvfrom(server_sockfd, message, sizeof(message), 0, (struct sockaddr*)&client_address, &client_len);
    printf("message from client: %s\n", message);

    // 向客户端发送数据
    char reply[] = "Hello, client!";
    sendto(server_sockfd, reply, sizeof(reply), 0, (struct sockaddr *)&client_address, client_len);

    // 关闭 Socket
    close(server_sockfd);

4.2 客户端实现

    // 创建 Socket
    int client_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 向服务端发送数据
    char message[] = "Hello, server!";
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET; // 地址族
    server_address.sin_port = htons(12345); // 端口号
    server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
    sendto(client_sockfd, message, sizeof(message), 0, (struct sockaddr *)&server_address, sizeof(server_address));

    // 接收服务端发送的数据
    char reply[1024];
    struct sockaddr_in reply_address;
    socklen_t reply_len = sizeof(reply_address);
    recvfrom(client_sockfd, reply, sizeof(reply), 0, (struct sockaddr *)&reply_address, &reply_len);
    printf("reply from server: %s\n", reply);

    // 关闭 Socket
    close(client_sockfd);

五、总结

Linux Socket 编程是进行网络通信的基础,对于理解网络通信原理、网络编程都非常重要。本文主要介绍了流式 Socket 和数据报式 Socket 的创建、命名、通信等基本操作,通过代码示例的方式进行详细阐述。

原创文章,作者:TCSYN,如若转载,请注明出处:https://www.506064.com/n/333476.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
TCSYNTCSYN
上一篇 2025-02-01 13:34
下一篇 2025-02-01 13:34

相关推荐

  • Python中使用socket传输图片

    本文将从多个方面介绍如何使用Python中的socket模块传输图片,涉及到准备工作、发送方部分和接收方部分的详细代码实现。 一、准备工作 在使用Python中的socket模块进…

    编程 2025-04-28
  • Python Socket阻塞问题的解析

    本文将从多个方面对Python socket阻塞问题进行详细阐述,包括阻塞的原因、影响、解决方法等等。 一、阻塞的原因 阻塞是指在等待某个事件的过程中,该进程无法处理其他任务,直到…

    编程 2025-04-27
  • 如何在Linux中添加用户并修改配置文件

    本文将从多个方面详细介绍在Linux系统下如何添加新用户并修改配置文件 一、添加新用户 在Linux系统下创建新用户非常简单,只需使用adduser命令即可。使用以下命令添加新用户…

    编程 2025-04-27
  • 如何解决linux jar包 invalid or corrupt jarfile问题

    对于许多开发人员和系统管理员在Linux环境下使用Java开发过程中遇到的一个常见的问题是 invalid or corrupt jarfile(无效或损坏的jar文件)错误。当您…

    编程 2025-04-27
  • C# Socket关闭后客户端仍可连接的解决方法

    对于C# Socket通信中的一些问题,多数人可能已经熟知,但是有些问题仍然困扰着一部分人,例如Socket关闭后,客户端仍然可以连接。本篇文章将在此问题为中心,围绕该问题的原因和…

    编程 2025-04-27
  • 在Linux上安装JRE并配置环境变量

    本文将从以下几个方面为您详细阐述如何在Linux系统上,通过自己账户安装JRE,并且配置环境变量。 一、安装JRE 在进行安装前,我们需要下载JRE的安装包并解压,可以从官方网站下…

    编程 2025-04-27
  • GTKAM:Linux下的照片管理器

    GTKAM是用于Linux操作系统的一款照片管理器,它支持多种相机及存储设备,并提供了一系列强大的工具,让用户可以方便地浏览、管理、编辑和导出照片。本文将从多个方面对GTKAM进行…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • 如何在Windows/Linux/MacOS下安装Python

    如果你对Python安装一无所知,本文将从多个方面对Python在Windows/Linux/MacOS下的安装做出详细阐述,为初学者提供帮助。 一、Windows下Python的…

    编程 2025-04-25

发表回复

登录后才能评论