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/zh-hant/n/333476.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
TCSYN的頭像TCSYN
上一篇 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

發表回復

登錄後才能評論