c++ socket網絡編程詳解

一、c socket 異步接收

c socket支持兩種類型的接收模式:阻塞模式和非阻塞模式,但是在大量的數據傳輸時,阻塞模式一定會造成數據的丟失和延遲,所以使用異步接收通常是一個更加可靠的解決辦法。在c++ socket中,我們可以使用select函數來實現異步接收。

while(1) {
    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock_fd, &read_fds);
    if(select(sock_fd+1, &read_fds, NULL, NULL, NULL) <= 0) {
         continue;
    }
    if(FD_ISSET(sock_fd, &read_fds)) {
         recv(sock_fd, buffer, size, 0);
    }
}

在上述代碼中,我們使用select函數監聽我們的socket,當有數據可讀時,便會進入recv函數來接收數據。

二、c socket 長連接

在網絡編程中,短連接是指每次請求都需要建立一個新的連接,而長連接則是可以一直保持連接狀態,在後續請求中都可以復用這個連接。

在c++ socket中,通過設置socket的選項SO_KEEPALIVE為1(開啟TCP心跳包機制)和TCP_NODELAY為1(禁用Nagle算法),我們可以實現長連接的功能。

int optval = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));

三、c socket技術

c++ socket編程中需要使用到的技術包括:TCP/IP協議、Socket編程、多線程、select的應用、數據加密和壓縮等。以下是一個基本的c++ socket示例代碼,實現了TCP連接和發送一條消息的功能。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[]) {

    int sock_fd;
    struct sockaddr_in server_addr;
    char msg[] = "Hello, world!";

    // create socket
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(sock_fd == -1) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // set server address
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // connect to server
    if(connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect failed");
        exit(EXIT_FAILURE);
    }

    // send message
    if(send(sock_fd, msg, strlen(msg), 0) < 0) {
        perror("send failed");
        exit(EXIT_FAILURE);
    }

    // close socket
    close(sock_fd);
    return 0;
}

四、c socket通訊源代碼

以下是一個基於select函數實現的簡單通信源代碼,包括服務器端和客戶端。

服務器端

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[]) {

    int listen_fd, max_fd, client_fd[FD_SETSIZE], conn_fd;
    int nready;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len;
    char buffer[256];
    fd_set read_set, all_set;
    int i;

    // create listen socket
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd == -1) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // set server address
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);

    // bind listen_fd
    if(bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // listen to client requests
    if(listen(listen_fd, 10) < 0) {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }

    max_fd = listen_fd;
    for(i = 0; i < FD_SETSIZE; i++)
        client_fd[i] = -1;

    FD_ZERO(&all_set);
    FD_SET(listen_fd, &all_set);

    printf("Server running...\n");

    while(1) {
        read_set = all_set;
        nready = select(max_fd+1, &read_set, NULL, NULL, NULL);
        if(nready < 0) {
            perror("select failed");
            exit(EXIT_FAILURE);
        }

        // if new client request
        if(FD_ISSET(listen_fd, &read_set)) {
            client_len = sizeof(client_addr);
            conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len);
            if(conn_fd < 0) {
                perror("accept failed");
                continue;
            }

            for(i = 0; i < FD_SETSIZE; i++) {
                if(client_fd[i]  max_fd) {
                max_fd = conn_fd;
            }
        }

        for(i = 0; i < FD_SETSIZE; i++) {
            if(client_fd[i] < 0)
                continue;
            if(FD_ISSET(client_fd[i], &read_set)) {
                memset(buffer, 0, sizeof(buffer));
                if(read(client_fd[i], buffer, sizeof(buffer)-1) == 0) {
                    printf("client[%d] closed\n", i);
                    close(client_fd[i]);
                    FD_CLR(client_fd[i], &all_set);
                    client_fd[i] = -1;
                } else {
                    printf("recv from client[%d]: %s\n", i, buffer);
                }
            }
        }
    }

    // close listen_fd
    close(listen_fd);
    return 0;
}

客戶端

#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[]) {

    int sock_fd;
    struct sockaddr_in server_addr;
    char buffer[256];

    // create socket
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(sock_fd == -1) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // set server address
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // connect to server
    if(connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect failed");
        exit(EXIT_FAILURE);
    }

    // send message
    strcpy(buffer, "Hello, world!");
    send(sock_fd, buffer, strlen(buffer), 0);
    printf("send message: %s\n", buffer);

    // close socket
    close(sock_fd);
    return 0;
}

五、c socket設置阻塞

在c++ socket編程中,我們默認使用阻塞模式來進行通信,即當進行讀寫操作時,程序將一直等待,直到I/O操作完成或者到達超時時間。

阻塞模式可以通過設置socket的O_NONBLOCK選項來實現非阻塞模式:

int flags = fcntl(sock_fd, F_GETFL, 0);
fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);

六、c socket傳輸

c++ socket中傳輸數據通常是通過send和recv函數進行。以下是一個基本的發送和接收數據的示例代碼:

發送數據

char buffer[256];
strcpy(buffer, "Hello, world!");
send(sock_fd, buffer, strlen(buffer), 0);

接收數據

char buffer[256];
memset(buffer, 0, sizeof(buffer));
recv(sock_fd, buffer, sizeof(buffer)-1, 0);
printf("recv message: %s\n", buffer);

七、c socket編程基礎

c++ socket編程的基礎可以分為以下幾個方面:

1. c socket 構造

c++ socket的構造需要使用socket函數,該函數包括三個參數:地址族、套接字類型和協議。

int sock_fd = socket(AF_INET, SOCK_STREAM, 0);

2. c socket函數

c++ socket編程需要使用一些關鍵的函數,包括bind、listen、accept、connect、send和recv等。以下是這些函數的基本使用方法:

bind函數

將socket與地址綁定:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen函數

告訴socket開始監聽連接請求:

listen(sock_fd, 10);
accept函數

接受客戶端的連接請求:

struct sockaddr_in client_addr;
int client_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &client_len);
connect函數

向服務器發起連接請求:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
send函數

發送數據到對端:

char buffer[256];
strcpy(buffer, "Hello, world!");
send(sock_fd, buffer, strlen(buffer), 0);
recv函數

從對端接收數據:

char buffer[256];
memset(buffer, 0, sizeof(buffer));
recv(sock_fd, buffer, sizeof(buffer)-1, 0);
printf("recv message: %s\n", buffer);

3. c語言socket通信

在c++ socket編程中,使用的通信協議通常是TCP/IP。

TCP/IP協議採用了面向連接的方式進行通信,可以保證數據的可靠性和完整性。但是,相比於UDP協議,TCP/IP協議的速度會稍微慢一些。

c++ socket編程中應用廣泛的通信方式有:單客戶端單線程、單客戶端多線程、多客戶端單線程和多客戶端多線程。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/271379.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-16 14:55
下一篇 2024-12-16 14:55

相關推薦

  • Python中使用socket傳輸圖片

    本文將從多個方面介紹如何使用Python中的socket模塊傳輸圖片,涉及到準備工作、發送方部分和接收方部分的詳細代碼實現。 一、準備工作 在使用Python中的socket模塊進…

    編程 2025-04-28
  • Python Socket阻塞問題的解析

    本文將從多個方面對Python socket阻塞問題進行詳細闡述,包括阻塞的原因、影響、解決方法等等。 一、阻塞的原因 阻塞是指在等待某個事件的過程中,該進程無法處理其他任務,直到…

    編程 2025-04-27
  • C# Socket關閉後客戶端仍可連接的解決方法

    對於C# Socket通信中的一些問題,多數人可能已經熟知,但是有些問題仍然困擾着一部分人,例如Socket關閉後,客戶端仍然可以連接。本篇文章將在此問題為中心,圍繞該問題的原因和…

    編程 2025-04-27
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分布式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25

發表回復

登錄後才能評論