国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux socket 搭建TCP服務(wù)器(C語言)

這篇具有很好參考價(jià)值的文章主要介紹了Linux socket 搭建TCP服務(wù)器(C語言)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

LinuxC 搭建簡單的TCP服務(wù)器

1. 問題

? 在標(biāo)題之前,先提幾個(gè)問題,方便下次查看理解。

  1. 什么是TCP
  2. TCP服務(wù)器需要用到哪些函數(shù)
  3. 如何簡單的搭建一個(gè)TCP服務(wù)器

2. 什么是TCP

? TCP 是一種傳輸層協(xié)議,可以提供可靠的數(shù)據(jù)傳輸服務(wù)。它是面向連接的,具有可靠性、流量控制、擁塞控制以及雙工通信的特點(diǎn)。

3. TCP 服務(wù)器需要用到哪些函數(shù)

1. socket

int socket(int domain, int type, int protocol); //聲明

int sockfd = socket(AF_INET, SOCK_STREAM, 0);   //示例

? socket 作用是用來創(chuàng)建一個(gè)文件描述符也成為套接字描述符,用于根據(jù)我們指定的協(xié)議族、數(shù)據(jù)類型和協(xié)議來分配一個(gè)套接字描述符以及它所用到的資源。函數(shù)調(diào)用失敗返回-1,調(diào)用成功返回正整數(shù)。

? 參數(shù)說明:

  • domain:指定協(xié)議族,常用的有 AF_INET(IPv4 地址)和 AF_INET6(IPv6 地址)、AF_LOCALAF_ROUTE 等。
  • type:指定套接字類型,有3種類型,常用的有 SOCK_STREAM(流式套接字,用于 TCP 協(xié)議)和 SOCK_DGRAM(數(shù)據(jù)報(bào)套接字,用于 UDP 協(xié)議)。第三種為 SOCK_RAW ,為原始類型,允許對(duì)底層協(xié)議(如 IP, ICMP)進(jìn)行直接訪問。
  • protocol:指定協(xié)議,通常設(shè)置為 0,表示讓系統(tǒng)根據(jù) domaintype 自動(dòng)選擇合適的協(xié)議。

? 底層邏輯:

? socket() 函數(shù)的底層邏輯主要涉及創(chuàng)建一個(gè)套接字?jǐn)?shù)據(jù)結(jié)構(gòu),注冊(cè)到內(nèi)核中,為該套接字分配一個(gè)唯一的文件描述符,并返回該文件描述符。具體步驟如下:

  1. 創(chuàng)建套接字?jǐn)?shù)據(jù)結(jié)構(gòu):根據(jù)指定的通信域、套接字類型和協(xié)議,創(chuàng)建一個(gè)套接字?jǐn)?shù)據(jù)結(jié)構(gòu),用于表示一個(gè)通信端點(diǎn)。
  2. 分配文件描述符:在內(nèi)核中分配一個(gè)文件描述符,用于標(biāo)識(shí)這個(gè)套接字。
  3. 注冊(cè)到內(nèi)核中:將套接字?jǐn)?shù)據(jù)結(jié)構(gòu)注冊(cè)到內(nèi)核的套接字表中,以便內(nèi)核能夠識(shí)別和管理這個(gè)套接字。
  4. 返回文件描述符:將分配的文件描述符返回給調(diào)用者,以便后續(xù)對(duì)套接字的操作。

2. bind

// 聲明
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 示例
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(2048);

if (-1 == bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)))
{
    perror("bind");
    return -1;
}

? bind() 函數(shù)用于將一個(gè)本地地址(包括 IP 地址和端口號(hào))綁定到一個(gè)套接字上,以便后續(xù)對(duì)該套接字的操作可以與指定的地址相關(guān)聯(lián)。當(dāng)你調(diào)用 bind() 函數(shù)時(shí),你正在告訴操作系統(tǒng)將特定的 IP 地址和端口號(hào)綁定到一個(gè)套接字上。這樣做的目的是為了讓該套接字在網(wǎng)絡(luò)上可以被唯一標(biāo)識(shí),并且只有特定地址和端口號(hào)的數(shù)據(jù)才能發(fā)送到這個(gè)套接字上。

? 參數(shù)說明:

  • sockfd:要綁定地址的套接字文件描述符。
  • addr:指向包含要綁定地址的結(jié)構(gòu)體的指針,通常是 struct sockaddr 類型的指針,需要根據(jù)套接字類型進(jìn)行類型轉(zhuǎn)換。
  • addrlen:指定地址結(jié)構(gòu)體的長度。

3. listen

? listen()函數(shù)用于將一個(gè)套接字描述符標(biāo)記為被動(dòng)套接字(socket()函數(shù)創(chuàng)建的套接字為主動(dòng)屬性),用于監(jiān)聽連接請(qǐng)求,等待客戶端的連接。所以它的作用是設(shè)置套接字為監(jiān)聽狀態(tài),等待客戶端的連接請(qǐng)求。

// 聲明
int listen(int sockfd, int backlog);

// 示例
listen(sockfd, 10);

? 參數(shù)說明:

  • sockf:要設(shè)置為監(jiān)聽狀態(tài)的套接字文件描述符。
  • backlog:待連接隊(duì)列的最大長度,即允許等待連接的客戶端數(shù)量。

4. accept

// 聲明
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);

? accept()函數(shù)用于從已監(jiān)聽的的套接字中接收一個(gè)連接請(qǐng)求,創(chuàng)建一個(gè)新的連接套接字,并返回新的套接字連接符。如果已完成連接隊(duì)列為空,則線程進(jìn)入阻塞狀態(tài)。如果accept函數(shù)執(zhí)行成功,則返回由內(nèi)核自動(dòng)生成的套接字描述符,表示服務(wù)器已與客戶端已經(jīng)建立連接;若執(zhí)行錯(cuò)誤則返回-1。

? 參數(shù)說明:

  • sockfd:已監(jiān)聽的套接字描述符(由 socket()函數(shù)返回的套接字描述符)
  • addr:一個(gè) sockaddr 的結(jié)構(gòu)體,用于存放發(fā)起連接請(qǐng)求的客戶端協(xié)議地址
  • addrlen:指向存放客戶端地址信息結(jié)構(gòu)體長度的指針。

5. recv

// 聲明
int recv(int sockfd, char * buf, int len, int flags);

// 示例
char buffer[128] = {0};
int recv_count = recv(clientfd, buffer, 128, 0);

? recv()函數(shù)用于接收已連接套接字發(fā)送的數(shù)據(jù)。從接收緩沖區(qū)中復(fù)制數(shù)據(jù),如果成功則返回復(fù)制的字節(jié)數(shù),失敗返回-1,對(duì)端斷開連接返回0。

? 參數(shù)說明:

  • sockfd:要接收數(shù)據(jù)的套接字描述符
  • buf:指向存放接收數(shù)據(jù)緩沖區(qū)的指針
  • len:接收緩沖區(qū)的長度
  • flags:接受操作的標(biāo)志位,通常為0,可以通過 ‘|’操作符連接到一起

6. send

// 聲明
int send(int sockfd, const void* buf, int len, int flags)

// 示例
char buffer[128] = {0};
int recv_count = recv(clientfd, buffer, 128, 0);
if (recv_count == 0)
{
    close(clientfd);
}
send(clientfd, buffer, recv_count, 0);

? send() 函數(shù)用于向已連接的套接字發(fā)送數(shù)據(jù),每個(gè)TCP連接的套接字都有一個(gè)發(fā)送緩沖區(qū)(buf 是存放數(shù)據(jù)的緩沖區(qū),不是發(fā)送緩沖區(qū)),調(diào)用send函數(shù)的過程是內(nèi)核將用戶的數(shù)據(jù)復(fù)制至TCP套接字的發(fā)送緩沖區(qū)的過程。send函數(shù)被調(diào)用時(shí),檢查TCP套接字中是否有發(fā)送數(shù)據(jù)。

? 如果沒有數(shù)據(jù)發(fā)送,則比較發(fā)送緩沖區(qū)長度和 send函數(shù)發(fā)送數(shù)據(jù)的長度 len,如果len大于套接字緩沖區(qū)長度,則返回錯(cuò)誤-1;如果發(fā)送緩沖區(qū)的大小足夠大,將數(shù)據(jù)發(fā)送至TCP發(fā)送緩沖區(qū),send函數(shù)將數(shù)據(jù)復(fù)制到發(fā)送緩沖區(qū)中。

? 如果有數(shù)據(jù)還未發(fā)送,則比較該緩沖區(qū)剩余空間和len的大小,如果len大于剩余空間,則一致等待,直到發(fā)送緩沖區(qū)中的數(shù)據(jù)發(fā)送完為止;如果len小于發(fā)送緩沖區(qū)剩余空間的大小,則將發(fā)送的數(shù)據(jù)復(fù)制到該緩沖區(qū)中。

? send函數(shù)發(fā)送成功時(shí),返回實(shí)際復(fù)制的字節(jié)數(shù),發(fā)送失敗時(shí),返回-1,另一端關(guān)閉連接時(shí),返回0。

? 參數(shù)說明:

  • sockfd:發(fā)送端套接字描述符
  • buf:待發(fā)送數(shù)據(jù)的緩沖區(qū)
  • len:待發(fā)送數(shù)據(jù)的字節(jié)長度
  • flags:發(fā)送操作的標(biāo)志位

4. 如何搭建一個(gè)簡單的服務(wù)器

1. 創(chuàng)建服務(wù)器sockfd

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

? 利用 socket函數(shù)創(chuàng)建一個(gè)套接字描述符,設(shè)置協(xié)議族,指定為TCP(SOCK_STREAM

2. 綁定客戶端IP和port

struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(2048);

if (-1 == bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)))
{
    perror("bind");
    return -1;
}

? 利用bind函數(shù)將sockfd與IP和端口綁定,此處 IP 任意(INADDR_ANY)端口為2048。

3. 將sockfd設(shè)置為監(jiān)聽模式

listen(sockfd, 10);

? listen函數(shù)將客戶端設(shè)置為監(jiān)聽狀態(tài),監(jiān)聽客戶端連接,設(shè)置最大連接為10個(gè)。

4. 接受客戶端連接

struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);

? 利用accept函數(shù)從已監(jiān)聽的的套接字中接收一個(gè)連接請(qǐng)求。返回客戶端套接字描述符clientfd。

5. 通信

while (1)
{
    char buffer[128] = {0};
    int recv_count = recv(clientfd, buffer, 128, 0);
    if (recv_count == 0)
    {
        break
    }
    send(clientfd, buffer, recv_count, 0);
}
close(clientfd);

? recv函數(shù)實(shí)現(xiàn)接受客戶端信息,send發(fā)送信息給客戶端。close函數(shù)回收clientfd文件資源

5. 實(shí)現(xiàn)并發(fā)

? 如果按照上述程序?qū)⒋a組合起來,實(shí)現(xiàn)的TCP服務(wù)器僅能與一臺(tái)客戶機(jī)進(jìn)行連接通信。為了實(shí)現(xiàn)并發(fā)功能,需要用到多線程的方法。

1. 線程回調(diào)函數(shù)

void* client_thread(void *arg)
{
    int clientfd = *(int *)arg;
    while (1)
    {
        char buffer[128] = {0};
        int recv_count = recv(clientfd, buffer, 128, 0);
        if (recv_count == 0)
        {
            break;
        }
        send(clientfd, buffer, recv_count, 0);
    }
}
close(clientfd);

? 該函數(shù)為線程的回調(diào)函數(shù),函數(shù)輸入一個(gè)客戶端clientfd

2. 根據(jù)客戶端連接請(qǐng)求創(chuàng)建線程

while (1)
{
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);

    pthread_t tid;
    pthread_create(&tid, NULL, client_thread, &clientfd);
}

? 每當(dāng)客戶端有新的連接請(qǐng)求時(shí),accept都會(huì)返回一個(gè)新的clientfd,然后pthread_create創(chuàng)建一個(gè)新線程,在該線程中服務(wù)器與該客戶端進(jìn)行通信。

6. 總結(jié)

? TCP 是一種傳輸層協(xié)議,可以提供可靠的數(shù)據(jù)傳輸服務(wù)。

? 在TCP服務(wù)器中用到了六個(gè)函數(shù)socket、bind、listen、accept、recvsend。

? 實(shí)現(xiàn)TCP服務(wù)器僅需將上述六個(gè)函數(shù)按順序運(yùn)用即可。我們還利用多線程的方法實(shí)現(xiàn)了一定量的并發(fā),但是依舊存在一些問題,它是一線程一請(qǐng)求的形式,如果請(qǐng)求過多,服務(wù)器將會(huì)資源耗盡,因此無法實(shí)現(xiàn)大的并發(fā)量。想要實(shí)現(xiàn)超大并發(fā),可以使用IO多路復(fù)用的功能。此處不做介紹,請(qǐng)聽下回分解。文章來源地址http://www.zghlxwxcb.cn/news/detail-854356.html

到了這里,關(guān)于Linux socket 搭建TCP服務(wù)器(C語言)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux后端服務(wù)器開發(fā)】socket套接字

    【Linux后端服務(wù)器開發(fā)】socket套接字

    目錄 一、socket 套接字概述 二、socket 函數(shù)接口 三、IP地址與端口號(hào)的網(wǎng)絡(luò)格式 四、TCP協(xié)議的本地通信C語言示例 socket 是什么? socket 本質(zhì)上是一個(gè)抽象的概念,它是一組用于 網(wǎng)絡(luò)通信的 API , 提供了一種統(tǒng)一的接口 ,使得應(yīng)用程序可以通過網(wǎng)絡(luò)進(jìn)行通信。在不同的操作系統(tǒng)

    2024年02月16日
    瀏覽(25)
  • 用C語言搭建TCP服務(wù)器/客戶端

    用C語言搭建TCP服務(wù)器/客戶端

    1.TCP流程圖 2.TCP編程 服務(wù)器 客戶端 ????????以上就是用c語言搭建的tcp服務(wù)器和客戶端,IP地址的地方可以根據(jù)自己本機(jī)的IP地址去修改(在命令提示符中可以使用ifconfig命令查看本機(jī)IP地址),端口號(hào)用的是6666,也可自己修改,但是IP地址和端口號(hào)服務(wù)器和客戶端必須一至。

    2024年02月09日
    瀏覽(24)
  • C語言再學(xué)習(xí) -- C語言搭建TCP服務(wù)器/客戶端

    TCP/UDP講過~ 參看:UNIX再學(xué)習(xí) – TCP/UDP 客戶機(jī)/服務(wù)器 參看:UNIX再學(xué)習(xí) – 網(wǎng)絡(luò)IPC:套接字 這里記錄一下可用的TCP服務(wù)器和客戶端代碼。 參看:用C語言搭建TCP服務(wù)器/客戶端

    2024年01月20日
    瀏覽(30)
  • Linux網(wǎng)絡(luò)編程:Socket服務(wù)器和客戶端實(shí)現(xiàn)雙方通信

    Linux網(wǎng)絡(luò)編程:Socket服務(wù)器和客戶端實(shí)現(xiàn)雙方通信

    目錄 一,什么是網(wǎng)絡(luò)編程 二,為什么使用端口號(hào) 三,TCP協(xié)議與UDP協(xié)議 ①TCP(傳輸控制協(xié)議) ②UDP(用戶數(shù)據(jù)報(bào)協(xié)議,User Data Protocol) ③總結(jié)歸納 四,Socket服務(wù)器和客戶端的開發(fā)流程 五,服務(wù)器和客戶端相關(guān)API說明 ①socket()函數(shù) ②bind()函數(shù) ③listen()函數(shù) ④accept()函數(shù) ⑤客戶端

    2024年02月11日
    瀏覽(34)
  • tcp連接阿里云linux服務(wù)器失敗

    原因: 自己程序bind的是127.0.0.1 應(yīng)該改成 bind 阿里云的私網(wǎng)地址 client連接的是阿里云公網(wǎng)地址 參考: 阿里云服務(wù)器,客戶端socket無法連接的問題 - 愛碼網(wǎng) 排查過程記錄: 1,安全組設(shè)置:有正常設(shè)置 2,防火墻有沒有允許端口:已經(jīng)允許 root@iZwz9hty12mlm1wlg0jzn0Z:~# ufw allow 808

    2024年02月06日
    瀏覽(24)
  • Linux 服務(wù)器 TCP 連接數(shù)參數(shù)調(diào)整

    服務(wù)器?es 或增加 nginx 要想增加處理能力,調(diào)整 TCP 連接數(shù)可以通過修改操作系統(tǒng)的TCP參數(shù)來實(shí)現(xiàn),以下是具體操作步驟,在此做下記錄: 1、查看系統(tǒng)TCP連接資源命令 2、調(diào)整操作系統(tǒng)的最大連接數(shù)限制? ?????????/etc/sysctl.conf 文件 ????????然后運(yùn)行以下命令使設(shè)置生

    2024年04月09日
    瀏覽(27)
  • Linux網(wǎng)絡(luò)編程:Socket套接字編程(Server服務(wù)器 Client客戶端)

    Linux網(wǎng)絡(luò)編程:Socket套接字編程(Server服務(wù)器 Client客戶端)

    文章目錄: 一:定義和流程分析 1.定義 2.流程分析? 3.網(wǎng)絡(luò)字節(jié)序 二:相關(guān)函數(shù)? IP地址轉(zhuǎn)換函數(shù)inet_pton inet_ntop(本地字節(jié)序 網(wǎng)絡(luò)字節(jié)序) socket函數(shù)(創(chuàng)建一個(gè)套接字) bind函數(shù)(給socket綁定一個(gè)服務(wù)器地址結(jié)構(gòu)(IP+port)) listen函數(shù)(設(shè)置最大連接數(shù)或者說能同時(shí)進(jìn)行三次握手的最

    2024年02月12日
    瀏覽(35)
  • Linux下網(wǎng)絡(luò)編程(3)——socket編程實(shí)戰(zhàn),如何構(gòu)建一個(gè)服務(wù)器和客戶端連接

    Linux下網(wǎng)絡(luò)編程(3)——socket編程實(shí)戰(zhàn),如何構(gòu)建一個(gè)服務(wù)器和客戶端連接

    ????????經(jīng)過前幾篇的介紹,本文我們將進(jìn)行編程實(shí)戰(zhàn),實(shí)現(xiàn)一個(gè)簡單地服務(wù)器和客戶端應(yīng)用程序。 編寫服務(wù)器程序 ???????? 編寫服務(wù)器應(yīng)用程序的流程如下: ????????①、調(diào)用 socket()函數(shù)打開套接字,得到套接字描述符; ????????②、調(diào)用 bind()函數(shù)將套接字

    2024年02月03日
    瀏覽(30)
  • 【python】TCP socket服務(wù)器 Demo

    【python】TCP socket服務(wù)器 Demo

    目錄 一、單線程服務(wù)器 二、多線程服務(wù)器 三、多線程服務(wù)器(發(fā)送和接收分離) 說明:只能連接一個(gè)客戶端 客戶端測試結(jié)果: 服務(wù)端測試結(jié)果: ?說明:可以支持連接多個(gè)客戶端 客戶端測試結(jié)果:? 服務(wù)端測試結(jié)果: 說明:?可以支持連接多個(gè)客戶端,并且能夠做到和多

    2024年02月09日
    瀏覽(22)
  • 【Linux環(huán)境搭建】用云服務(wù)器搭建Linux環(huán)境

    【Linux環(huán)境搭建】用云服務(wù)器搭建Linux環(huán)境

    目錄 1. 我們?yōu)槭裁匆獙W(xué)Linux 2. 云服務(wù)器購買 3. 遠(yuǎn)程連接云服務(wù)器 4. 如何創(chuàng)建新用戶? ?5. 第一個(gè)Linux程序 總結(jié): 寫在最后: 作為一個(gè)程序員,你必須學(xué)好Linux,至于為什么,這個(gè)問題, 在我們?nèi)蘸蟮膶W(xué)習(xí)中,自然會(huì)慢慢展現(xiàn)出來,而校招對(duì)于Linux也有掌握的要求, 所以我們

    2024年02月03日
    瀏覽(92)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包