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

套接字通信(附帶單線程TCP套接字通信代碼)

這篇具有很好參考價(jià)值的文章主要介紹了套接字通信(附帶單線程TCP套接字通信代碼)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

套接字-Socket

1. 概念

1.1 局域網(wǎng)和廣域網(wǎng)

局域網(wǎng)(LAN)和廣域網(wǎng)(WAN)是兩種不同范圍的計(jì)算機(jī)網(wǎng)絡(luò),它們用于連接多臺(tái)計(jì)算機(jī)以實(shí)現(xiàn)數(shù)據(jù)共享和通信。

  1. 局域網(wǎng)(LAN):
    • 定義: 局域網(wǎng)是一個(gè)較小范圍內(nèi)的網(wǎng)絡(luò),通常限定在某個(gè)地理區(qū)域,比如一個(gè)辦公室、學(xué)?;蛘呒彝?。
    • 范圍: LAN 的范圍通常在幾百米到幾千米之間。
    • 連接設(shè)備: 局域網(wǎng)連接的設(shè)備可以是計(jì)算機(jī)、打印機(jī)、服務(wù)器等,通過(guò)局域網(wǎng)內(nèi)的設(shè)備可以方便地共享資源和信息。
    • 傳輸速度: 由于較小的范圍,局域網(wǎng)通常具有較高的傳輸速度和較低的延遲。
  2. 廣域網(wǎng)(WAN):
    • 定義: 廣域網(wǎng)是一個(gè)覆蓋范圍更廣泛的網(wǎng)絡(luò),可以連接跨越城市、國(guó)家甚至是全球的多個(gè)局域網(wǎng)。
    • 范圍: WAN 的范圍較大,可以覆蓋從幾千千米到全球范圍。
    • 連接設(shè)備: 廣域網(wǎng)連接的設(shè)備可以是分布在不同地理位置的局域網(wǎng),通過(guò) WAN,這些設(shè)備可以進(jìn)行遠(yuǎn)程通信和數(shù)據(jù)交換。
    • 傳輸速度: 由于覆蓋較大范圍,廣域網(wǎng)的傳輸速度通常相對(duì)較慢,而且可能存在較高的延遲。
  3. 連接方式:
    • 局域網(wǎng): 通常通過(guò)以太網(wǎng)技術(shù)、Wi-Fi等局域網(wǎng)技術(shù)進(jìn)行連接。
    • 廣域網(wǎng): 使用各種通信技術(shù),包括光纖、衛(wèi)星、電話線等,以連接不同地理位置的網(wǎng)絡(luò)。
  4. 應(yīng)用場(chǎng)景:
    • 局域網(wǎng): 用于組織內(nèi)部、學(xué)校、家庭等相對(duì)小范圍的網(wǎng)絡(luò)需求。
    • 廣域網(wǎng): 用于連接分布在不同城市、國(guó)家或全球范圍內(nèi)的組織和機(jī)構(gòu),實(shí)現(xiàn)遠(yuǎn)程通信和資源共享。

總的來(lái)說(shuō),局域網(wǎng)和廣域網(wǎng)在范圍、連接設(shè)備、傳輸速度以及應(yīng)用場(chǎng)景上有明顯的區(qū)別,它們?cè)诰W(wǎng)絡(luò)體系中協(xié)同工作,為不同規(guī)模和需求的組織提供了靈活的網(wǎng)絡(luò)解決方案。

1.2 IP

IP,或稱為Internet Protocol(互聯(lián)網(wǎng)協(xié)議),是一種**在計(jì)算機(jī)網(wǎng)絡(luò)中用于標(biāo)識(shí)和定位設(shè)備(如計(jì)算機(jī)、路由器、服務(wù)器等)的通信協(xié)議。**IP地址是在Internet Protocol中使用的標(biāo)識(shí)符,用于唯一標(biāo)識(shí)網(wǎng)絡(luò)中的每個(gè)設(shè)備。

  • IPv4: 使用一個(gè)32位的整形數(shù)描述一個(gè)IP地址,4個(gè)字節(jié),int型
  • IPv6: 使用一個(gè)128位的整形數(shù)描述一個(gè)IP地址,16個(gè)字節(jié)
  • 查看IP地址:
# linux
$ ifconfig

# windows
$ ipconfig

# 測(cè)試網(wǎng)絡(luò)是否暢通
# 主機(jī)a: 192.168.1.11
# 當(dāng)前主機(jī): 192.168.1.12
$ ping 192.168.1.11     # 測(cè)試是否可用連接局域網(wǎng)
$ ping www.baidu.com    # 測(cè)試是否可用連接外網(wǎng)

# 特殊的IP地址: 127.0.0.1  ==> 和本地的IP地址是等價(jià)的
# 假設(shè)當(dāng)前電腦沒(méi)有聯(lián)網(wǎng), 就沒(méi)有IP地址, 又要做網(wǎng)絡(luò)測(cè)試, 可用使用 127.0.0.1 進(jìn)行本地測(cè)試
1.3 端口

端口是計(jì)算機(jī)網(wǎng)絡(luò)中用于**標(biāo)識(shí)進(jìn)程或服務(wù)的抽象概念。在一臺(tái)計(jì)算機(jī)上,可以同時(shí)運(yùn)行多個(gè)網(wǎng)絡(luò)應(yīng)用程序或服務(wù),而端口就是用來(lái)區(qū)分它們的一種方式**。端口通過(guò)數(shù)字來(lái)標(biāo)識(shí),范圍從0到65535。

  1. 端口號(hào):
    • 端口號(hào)是一個(gè)16位的數(shù)字,用于唯一標(biāo)識(shí)計(jì)算機(jī)上運(yùn)行的特定服務(wù)或應(yīng)用程序。端口號(hào)范圍從0到65535,其中0到1023是被稱為"知名端口",用于一些常見(jiàn)的服務(wù),如HTTP(80端口)和HTTPS(443端口)等。
  2. TCP和UDP端口:
    • 端口分為TCP端口和UDP端口,這取決于應(yīng)用程序所使用的傳輸協(xié)議。TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報(bào)協(xié)議)是兩種常見(jiàn)的傳輸協(xié)議,它們使用不同的端口范圍。例如,HTTP通常使用TCP的80端口,而DNS服務(wù)通常使用UDP的53端口。
1.4 網(wǎng)絡(luò)分層模型

網(wǎng)絡(luò)分層模型是一種將計(jì)算機(jī)網(wǎng)絡(luò)功能劃分為不同層次的概念性框架,以簡(jiǎn)化網(wǎng)絡(luò)設(shè)計(jì)、管理和維護(hù)。其中最經(jīng)典和廣泛使用的分層模型是OSI(開(kāi)放系統(tǒng)互聯(lián))模型和TCP/IP模型。以下是這兩個(gè)模型的概述:

  1. OSI模型(開(kāi)放系統(tǒng)互聯(lián)模型): OSI模型是由國(guó)際標(biāo)準(zhǔn)化組織(ISO)定義的一種七層模型,每一層都執(zhí)行特定的功能,且每一層的功能都建立在下一層提供的服務(wù)之上。這七個(gè)層次從下到上依次是:

    • 物理層(Physical Layer): 處理物理連接和傳輸介質(zhì),例如電纜、光纖等。
    • 數(shù)據(jù)鏈路層(Data Link Layer): 負(fù)責(zé)將物理層的數(shù)據(jù)劃分成幀,并提供數(shù)據(jù)的可靠傳輸。
    • 網(wǎng)絡(luò)層(Network Layer): 處理數(shù)據(jù)包的路由和轉(zhuǎn)發(fā),實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的通信。
    • 傳輸層(Transport Layer): 提供端到端的通信控制,包括數(shù)據(jù)的分段、重組和錯(cuò)誤檢測(cè)。
    • 會(huì)話層(Session Layer): 管理不同應(yīng)用程序之間的對(duì)話和會(huì)話。
    • 表示層(Presentation Layer): 處理數(shù)據(jù)的格式轉(zhuǎn)換、加密和壓縮等。
    • 應(yīng)用層(Application Layer): 提供網(wǎng)絡(luò)服務(wù)和應(yīng)用程序之間的接口。
  2. TCP/IP模型: TCP/IP模型是互聯(lián)網(wǎng)上廣泛使用的模型,它包含四個(gè)層次,從下到上依次是:

  • 網(wǎng)絡(luò)接口層(Network Interface Layer): 類似于OSI的物理層和數(shù)據(jù)鏈路層,處理硬件設(shè)備和網(wǎng)絡(luò)的連接。

  • 網(wǎng)絡(luò)層(Internet Layer): 類似于OSI的網(wǎng)絡(luò)層,負(fù)責(zé)數(shù)據(jù)包的路由和轉(zhuǎn)發(fā)。(IP)

  • 傳輸層(Transport Layer): 類似于OSI的傳輸層,提供端到端的通信控制。(TCP, UDP)

  • 應(yīng)用層(Application Layer): 同樣對(duì)應(yīng)OSI的應(yīng)用層,提供網(wǎng)絡(luò)服務(wù)和應(yīng)用程序之間的接口。(HTTP, FTP, DNS)

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

1.5 數(shù)據(jù)封裝

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

2. socket編程

與套接字相關(guān)的函數(shù)被包含在頭文件sys/socket.h中。

2.1 字節(jié)序

字節(jié)序(Byte Order)指的是在計(jì)算機(jī)中,多字節(jié)數(shù)據(jù)類型的存儲(chǔ)順序(字符串就沒(méi)有)。具體來(lái)說(shuō),它指定了在內(nèi)存中多字節(jié)值的字節(jié)排列順序。在多字節(jié)數(shù)據(jù)類型中,比如16位、32位或64位的整數(shù),字節(jié)序定義了它們?cè)趦?nèi)存中的存儲(chǔ)方式。

有兩種主要的字節(jié)序:大端序(Big Endian)和小端序(Little Endian)。

  1. 大端序(Big Endian):
    • 在大端序中,多字節(jié)數(shù)據(jù)的最高有效字節(jié)(Most Significant Byte,MSB)存儲(chǔ)在最低的內(nèi)存地址,而最低有效字節(jié)(Least Significant Byte,LSB)存儲(chǔ)在最高的內(nèi)存地址。
    • 舉例來(lái)說(shuō),對(duì)于十六進(jìn)制值0x12345678
      • 大端序:12 34 56 78
  2. 小端序(Little Endian):
    • 在小端序中,多字節(jié)數(shù)據(jù)的最低有效字節(jié)存儲(chǔ)在最低的內(nèi)存地址,而最高有效字節(jié)存儲(chǔ)在最高的內(nèi)存地址。
    • 對(duì)于同樣的十六進(jìn)制值0x12345678
      • 小端序:78 56 34 12
// 有一個(gè)16進(jìn)制的數(shù), 有32位 (int): 0xab5c01ff
// 字節(jié)序, 最小的單位: char 字節(jié), int 有4個(gè)字節(jié), 需要將其拆分為4份
// 一個(gè)字節(jié) unsigned char, 最大值是 255(十進(jìn)制) ==> ff(16進(jìn)制) 
                 內(nèi)存低地址位                內(nèi)存的高地址位
--------------------------------------------------------------------------->
小端:         0xff        0x01        0x5c        0xab
大端:         0xab        0x5c        0x01        0xff

在進(jìn)行跨平臺(tái)數(shù)據(jù)交換時(shí),需要考慮字節(jié)序的問(wèn)題,通常使用網(wǎng)絡(luò)字節(jié)序(也稱為大端序)來(lái)確保數(shù)據(jù)的正確傳輸。

2.2 主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換函數(shù)(端口)

從主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換函數(shù):htons、htonl;從網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的轉(zhuǎn)換函數(shù):ntohs、ntohl。

  • htons():主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的16位整數(shù)轉(zhuǎn)換。
  • htonl():主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的32位整數(shù)轉(zhuǎn)換。
#include <arpa/inet.h>

uint16_t hostShort = 0x1234;
uint32_t hostLong = 0x12345678;

uint16_t networkShort = htons(hostShort);
uint32_t networkLong = htonl(hostLong);
  • ntohs():網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的16位整數(shù)轉(zhuǎn)換。
  • ntohl():網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的32位整數(shù)轉(zhuǎn)換。
#include <arpa/inet.h>

uint16_t networkShort = 0x3412;
uint32_t networkLong = 0x78563412;

uint16_t hostShort = ntohs(networkShort);
uint32_t hostLong = ntohl(networkLong);
2.3 IP地址轉(zhuǎn)換

主機(jī)字節(jié)序的IP地址是字符串, 網(wǎng)絡(luò)字節(jié)序IP地址是整形

雖然IP地址本質(zhì)是一個(gè)整形數(shù),但是在使用的過(guò)程中都是通過(guò)一個(gè)字符串來(lái)描述,下面的函數(shù)描述了如何將一個(gè)字符串類型的IP地址進(jìn)行大小端轉(zhuǎn)換:

// 主機(jī)字節(jié)序的IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序
int inet_pton(int af, const char *src, void *dst); 
  • af:地址族,可以是 AF_INET 表示IPv4,或者 AF_INET6 表示IPv6。
  • src:以字符串形式表示的IP地址。
  • dst:用于存儲(chǔ)轉(zhuǎn)換后的二進(jìn)制地址的緩沖區(qū)。

函數(shù)的返回值是一個(gè)整數(shù),如果轉(zhuǎn)換成功,則返回 1,如果提供的地址無(wú)效,則返回 0,如果發(fā)生錯(cuò)誤,則返回 -1。

  • 將計(jì)算機(jī)內(nèi)部使用的二進(jìn)制格式的IPv4和IPv6地址表示轉(zhuǎn)換為人類可讀形式的字符串表示法的函數(shù)
#include <arpa/inet.h>
// 將大端的整形數(shù), 轉(zhuǎn)換為小端的點(diǎn)分十進(jìn)制的IP地址        
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
  • af:地址族,可以是 AF_INET 表示IPv4,或者 AF_INET6 表示IPv6。
  • src:指向包含二進(jìn)制格式地址的指針。
  • dst:用于存儲(chǔ)轉(zhuǎn)換后的字符串的緩沖區(qū)。
  • size:緩沖區(qū)的大小。

函數(shù)的返回值是一個(gè)指向存儲(chǔ)在 dst 中的字符串的指針,失敗返回 NULL 并設(shè)置 errno。

3. 套接字函數(shù)

3.1 sockaddr數(shù)據(jù)結(jié)構(gòu)

sockaddr 是一個(gè)通用的套接字地址結(jié)構(gòu),用于在網(wǎng)絡(luò)編程中表示網(wǎng)絡(luò)地址信息。

// 在寫(xiě)數(shù)據(jù)的時(shí)候不好用
struct sockaddr {
	sa_family_t sa_family;       // 地址族協(xié)議, ipv4
	char        sa_data[14];     // 端口(2字節(jié)) + IP地址(4字節(jié)) + 填充(8字節(jié))
}

typedef unsigned short  uint16_t;
typedef unsigned int    uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

struct in_addr
{
    in_addr_t s_addr;
};  

// sizeof(struct sockaddr) == sizeof(struct sockaddr_in)
struct sockaddr_in
{
    sa_family_t sin_family;		/* 地址族協(xié)議: AF_INET */
    in_port_t sin_port;         /* 端口, 2字節(jié)-> 大端  */
    struct in_addr sin_addr;    /* IP地址, 4字節(jié) -> 大端  */
    /* 填充 8字節(jié) */
    unsigned char sin_zero[sizeof (struct sockaddr) - sizeof(sin_family) -
               sizeof (in_port_t) - sizeof (struct in_addr)];
};  

這些結(jié)構(gòu)體用于在套接字編程中表示網(wǎng)絡(luò)地址,通過(guò)將 sockaddr_in 結(jié)構(gòu)體的地址轉(zhuǎn)換為 sockaddr 結(jié)構(gòu)體的地址,可以在函數(shù)參數(shù)中使用通用的 sockaddr 結(jié)構(gòu)。例如,在調(diào)用套接字創(chuàng)建函數(shù)時(shí),可以將一個(gè) sockaddr_in 結(jié)構(gòu)體的地址強(qiáng)制轉(zhuǎn)換為 sockaddr 結(jié)構(gòu)體的地址,以便在不同的網(wǎng)絡(luò)函數(shù)中使用。

3.2 套接字函數(shù)

使用套接字通信函數(shù)需要包含頭文件<arpa/inet.h>,包含了這個(gè)頭文件<sys/socket.h>就不用在包含了。

  • 創(chuàng)建套接字函數(shù)
// 創(chuàng)建一個(gè)套接字
int socket(int domain, int type, int protocol);

參數(shù):

  • domain: 使用的地址族協(xié)議
    • AF_INET: 使用IPv4格式的ip地址
    • AF_INET6: 使用IPv4格式的ip地址
  • type:
    • SOCK_STREAM: 使用流式的傳輸協(xié)議(TCP)
    • SOCK_DGRAM: 使用報(bào)式(報(bào)文)的傳輸協(xié)議(UDP)
  • protocol: 一般寫(xiě)0即可, 使用默認(rèn)的協(xié)議
    • SOCK_STREAM: 流式傳輸默認(rèn)使用的是tcp
    • SOCK_DGRAM: 報(bào)式傳輸默認(rèn)使用的udp

返回值:

  • 成功: 可用于套接字通信的文件描述符
  • 失敗: -1

函數(shù)的返回值是一個(gè)文件描述符,通過(guò)這個(gè)文件描述符可以操作內(nèi)核中的某一塊內(nèi)存,網(wǎng)絡(luò)通信是基于這個(gè)文件描述符來(lái)完成的。

  • 綁定端口
// 將文件描述符和本地的IP與端口進(jìn)行綁定   
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

參數(shù):

  • sockfd: 監(jiān)聽(tīng)的文件描述符, 通過(guò)socket()調(diào)用得到的返回值
  • addr: 傳入?yún)?shù), 要綁定的IP和端口信息需要初始化到這個(gè)結(jié)構(gòu)體中,IP和端口要轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序
  • addrlen: 參數(shù)addr指向的內(nèi)存大小, sizeof(struct sockaddr)

返回值:成功返回0,失敗返回-1

  • 設(shè)置監(jiān)聽(tīng)
// 給監(jiān)聽(tīng)的套接字設(shè)置監(jiān)聽(tīng)
int listen(int sockfd, int backlog);

參數(shù):

  • sockfd: 文件描述符, 可以通過(guò)調(diào)用socket()得到,在監(jiān)聽(tīng)之前必須要綁定 bind()
  • backlog: 同時(shí)能處理的最大連接要求,最大值為128

返回值:函數(shù)調(diào)用成功返回0,調(diào)用失敗返回 -1

  • 等待并接受客戶端的連接請(qǐng)求
// 等待并接受客戶端的連接請(qǐng)求, 建立新的連接, 會(huì)得到一個(gè)新的文件描述符(通信的)		
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

參數(shù):

  • sockfd: 監(jiān)聽(tīng)的文件描述符
  • addr: 傳出參數(shù), 里邊存儲(chǔ)了建立連接的客戶端的地址信息
  • addrlen: 傳入傳出參數(shù),用于存儲(chǔ)addr指向的內(nèi)存大小

返回值:函數(shù)調(diào)用成功,得到一個(gè)文件描述符, 用于和建立連接的這個(gè)客戶端通信,調(diào)用失敗返回 -1

這個(gè)函數(shù)是一個(gè)阻塞函數(shù),當(dāng)沒(méi)有新的客戶端連接請(qǐng)求的時(shí)候,該函數(shù)阻塞;當(dāng)檢測(cè)到有新的客戶端連接請(qǐng)求時(shí),阻塞解除,新連接就建立了,得到的返回值也是一個(gè)文件描述符,基于這個(gè)文件描述符就可以和客戶端通信了。

  • 接收數(shù)據(jù)
// 接收數(shù)據(jù)
ssize_t read(int sockfd, void *buf, size_t size);
ssize_t recv(int sockfd, void *buf, size_t size, int flags);

參數(shù):

  • sockfd: 用于通信的文件描述符, accept() 函數(shù)的返回值
  • buf: 指向一塊有效內(nèi)存, 用于存儲(chǔ)接收是數(shù)據(jù)
  • size: 參數(shù)buf指向的內(nèi)存的容量
  • flags: 特殊的屬性, 一般不使用, 指定為 0

返回值:

  • 大于0:實(shí)際接收的字節(jié)數(shù)
  • 等于0:對(duì)方斷開(kāi)了連接
  • -1:接收數(shù)據(jù)失敗了

如果連接沒(méi)有斷開(kāi),接收端接收不到數(shù)據(jù),接收數(shù)據(jù)的函數(shù)會(huì)阻塞等待數(shù)據(jù)到達(dá),數(shù)據(jù)到達(dá)后函數(shù)解除阻塞,開(kāi)始接收數(shù)據(jù),當(dāng)發(fā)送端斷開(kāi)連接,接收端無(wú)法接收到任何數(shù)據(jù),但是這時(shí)候就不會(huì)阻塞了,函數(shù)直接返回0。

  • 發(fā)送數(shù)據(jù)
// 發(fā)送數(shù)據(jù)的函數(shù)
ssize_t write(int fd, const void *buf, size_t len);
ssize_t send(int fd, const void *buf, size_t len, int flags);

參數(shù):

  • fd: 通信的文件描述符, accept() 函數(shù)的返回值
  • buf: 傳入?yún)?shù), 要發(fā)送的字符串
  • len: 要發(fā)送的字符串的長(zhǎng)度
  • flags: 特殊的屬性, 一般不使用, 指定為 0

返回值:

  • 大于0:實(shí)際發(fā)送的字節(jié)數(shù),和參數(shù)len是相等的
  • -1:發(fā)送數(shù)據(jù)失敗了

成功連接服務(wù)器之后, 客戶端會(huì)自動(dòng)隨機(jī)綁定一個(gè)端口

// 服務(wù)器端調(diào)用accept()的函數(shù), 第二個(gè)參數(shù)存儲(chǔ)的就是客戶端的IP和端口信息
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

參數(shù):

  • sockfd: 通信的文件描述符, 通過(guò)調(diào)用socket()函數(shù)就得到了
  • addr: 存儲(chǔ)了要連接的服務(wù)器端的地址信息: iP 和 端口,這個(gè)IP和端口也需要轉(zhuǎn)換為大端然后再賦值
  • addrlen: addr指針指向的內(nèi)存的大小 sizeof(struct sockaddr)

返回值:連接成功返回0,連接失敗返回-1

4. TCP通信流程

TCP是一個(gè)**面向連接的,可靠的,流式傳輸協(xié)議,這個(gè)協(xié)議是一個(gè)傳輸層協(xié)議**。它確保數(shù)據(jù)在發(fā)送和接收之間按順序、可靠地傳輸。

  • 面向連接:是一個(gè)雙向連接,通過(guò)三次握手完成,斷開(kāi)連接需要通過(guò)四次揮手完成。
  • 安全:tcp通信過(guò)程中,會(huì)對(duì)發(fā)送的每一數(shù)據(jù)包都會(huì)進(jìn)行校驗(yàn), 如果發(fā)現(xiàn)數(shù)據(jù)丟失, 會(huì)自動(dòng)重傳
  • 流式傳輸:發(fā)送端和接收端處理數(shù)據(jù)的速度,數(shù)據(jù)的量都可以不一致

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

4.1 服務(wù)器端通信流程
  1. 創(chuàng)建用于監(jiān)聽(tīng)的套接字, 這個(gè)套接字是一個(gè)文件描述符**socket()**
  2. 將得到的監(jiān)聽(tīng)的文件描述符和本地的IP 端口進(jìn)行綁定 bind()
  3. 設(shè)置監(jiān)聽(tīng)(成功之后開(kāi)始監(jiān)聽(tīng), 監(jiān)聽(tīng)的是客戶端的連接) listen()
  4. 等待并接受客戶端的連接請(qǐng)求, 建立新的連接, 會(huì)得到一個(gè)新的文件描述符(通信的),沒(méi)有新連接請(qǐng)求就阻塞 accept()
  5. 通信,讀寫(xiě)操作默認(rèn)都是阻塞的 read()/recv() write()/send()
  6. 斷開(kāi)連接, 關(guān)閉套接字 close()

在tcp的服務(wù)器端, 有兩類文件描述符

監(jiān)聽(tīng)的文件描述符

  • 只需要有一個(gè)
  • 不負(fù)責(zé)和客戶端通信, 負(fù)責(zé)檢測(cè)客戶端的連接請(qǐng)求, 檢測(cè)到之后調(diào)用accept就可以建立新的連接

通信的文件描述符

  • 負(fù)責(zé)和建立連接的客戶端通信
  • 如果有N個(gè)客戶端和服務(wù)器建立了新的連接, 通信的文件描述符就有N個(gè),每個(gè)客戶端和服務(wù)器都對(duì)應(yīng)一個(gè)通信的文件描述符

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

文件描述符對(duì)應(yīng)的內(nèi)存結(jié)構(gòu):

  • 一個(gè)文件文件描述符對(duì)應(yīng)兩塊內(nèi)存, 一塊內(nèi)存是讀緩沖區(qū), 一塊內(nèi)存是寫(xiě)緩沖區(qū)
  • 讀數(shù)據(jù): 通過(guò)文件描述符將內(nèi)存中的數(shù)據(jù)讀出, 這塊內(nèi)存稱之為讀緩沖區(qū)
  • 寫(xiě)數(shù)據(jù): 通過(guò)文件描述符將數(shù)據(jù)寫(xiě)入到某塊內(nèi)存中, 這塊內(nèi)存稱之為寫(xiě)緩沖區(qū)

服務(wù)器端和客戶端用文件描述夫建立連接和發(fā)送接收數(shù)據(jù)的流程:

監(jiān)聽(tīng)的文件描述符:

  • 客戶端的連接請(qǐng)求會(huì)發(fā)送到服務(wù)器端監(jiān)聽(tīng)的文件描述符的讀緩沖區(qū)中
  • 讀緩沖區(qū)中有數(shù)據(jù), 說(shuō)明有新的客戶端連接
  • 調(diào)用accept()函數(shù), 這個(gè)函數(shù)會(huì)檢測(cè)監(jiān)聽(tīng)文件描述符的讀緩沖區(qū)
    • 檢測(cè)不到數(shù)據(jù), 該函數(shù)阻塞
    • 如果檢測(cè)到數(shù)據(jù), 解除阻塞, 新的連接建立

通信的文件描述符:

  • 客戶端和服務(wù)器端都有通信的文件描述符
  • 發(fā)送數(shù)據(jù):調(diào)用函數(shù) write() / send(),數(shù)據(jù)進(jìn)入到內(nèi)核中
    • 數(shù)據(jù)并沒(méi)有被發(fā)送出去, 而是將數(shù)據(jù)寫(xiě)入到了通信的文件描述符對(duì)應(yīng)的寫(xiě)緩沖區(qū)中
    • 內(nèi)核檢測(cè)到通信的文件描述符寫(xiě)緩沖區(qū)中有數(shù)據(jù), 內(nèi)核會(huì)將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)中
  • 接收數(shù)據(jù): 調(diào)用的函數(shù) read() / recv(), 從內(nèi)核讀數(shù)據(jù)
    • 數(shù)據(jù)如何進(jìn)入到內(nèi)核程序猿不需要處理, 數(shù)據(jù)進(jìn)入到通信的文件描述符的讀緩沖區(qū)中
    • 數(shù)據(jù)進(jìn)入到內(nèi)核, 必須使用通信的文件描述符, 將數(shù)據(jù)從讀緩沖區(qū)中讀出即可
4.2 客戶端的通信流程

在單線程的情況下客戶端通信的文件描述符有一個(gè), 沒(méi)有監(jiān)聽(tīng)的文件描述符

  1. 創(chuàng)建一個(gè)通信的套接字 socket()
  2. 連接服務(wù)器, 需要知道服務(wù)器綁定的IP和端口 connect()
  3. 通信 read()/recv() write()/send()
  4. 斷開(kāi)連接, 關(guān)閉文件描述符(套接字) close()
4.3 通信代碼

從通信流程中可以看出, 客戶端在connect()的時(shí)候, 需要知道服務(wù)器的IP和端口號(hào), 所以必須要先啟動(dòng)服務(wù)器端(bind()函數(shù)綁定), 才能進(jìn)行通信

基于tcp的服務(wù)器端通信代碼
// server.cpp
// Created by 47468 on 2024/1/19.
//
#include <iostream>
#include "arpa/inet.h"
using namespace std;
#include "string.h"
#include "unistd.h"

int main() {
    // 1. 創(chuàng)建監(jiān)聽(tīng)的套接字
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1){
        perror("socket");
        exit(0);
    }

    // 2. 將socket()返回值和本地的IP端口綁定到一起
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(10000);

    // INADDR_ANY代表本機(jī)的所有IP, 假設(shè)有三個(gè)網(wǎng)卡就有三個(gè)IP地址
    // 這個(gè)宏可以代表任意一個(gè)IP地址
    // 這個(gè)宏一般用于本地的綁定操作
    addr.sin_addr.s_addr = INADDR_ANY;

    // inet_pton(AF_INET, "192.168.237.131", &addr.sin_addr.s_addr);

    int ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret == -1){
        perror("bind");
        exit(0);
    }

    // 3. 設(shè)置監(jiān)聽(tīng)
    ret = listen(lfd, 128);
    if(ret == -1){
        perror("listen");
        exit(0);
    }

    // 4. 阻塞等待并接受客戶端連接
    struct sockaddr_in cliaddr;
    int clilen = sizeof(cliaddr);
    int cfd = accept(lfd, (struct sockaddr*)&cliaddr, (socklen_t*)(&clilen));
    if(cfd == -1){
        perror("accept");
        exit(0);
    }

    // 打印客戶端的地址信息
    char ip[24] = {0};
    cout << "客戶端的ip地址: " << inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, ip, sizeof(ip))
         << ", 端口: " << ntohs(cliaddr.sin_port) << endl;

    // 5. 和客戶端通信
    while(1){
        // 接收數(shù)據(jù)
        char buf[1024];
        memset(buf, 0, sizeof(buf));
        int len = read(cfd, buf, sizeof(buf));
        if(len > 0){
            cout << "客戶端say: " << buf << endl;
            write(cfd, buf, len);
        } else if (len == 0){
            cout << "客戶端斷開(kāi)了連接" << endl;
            break;
        } else {
            perror("read");
            break;
        }
    }
    close(lfd);
    close(cfd);

    return 0;
}
基于tcp通信的客戶端通信代碼
// client.cpp
// Created by 47468 on 2024/1/19.
//
#include <iostream>
#include "arpa/inet.h"
using namespace std;
#include "string.h"
#include "unistd.h"

int main() {
    // 1. 創(chuàng)建監(jiān)聽(tīng)的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1){
        perror("socket");
        exit(0);
    }

    // 2. 鏈接服務(wù)器
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(10000); // 大端端口
    inet_pton(AF_INET, "192.168.110.129", &addr.sin_addr.s_addr);

    int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret == -1){
        perror("connect");
        exit(0);
    }

    // 3. 和服務(wù)器通信
    int num = 0;
    while(1){
        // 發(fā)送數(shù)據(jù)
        char buf[1024];
        sprintf(buf, "你好服務(wù)器...%d\n", num++);
        write(fd, buf, strlen(buf) + 1);

        // 接收數(shù)據(jù)
        memset(buf, 0, sizeof(buf));
        int len = read(fd, buf, sizeof(buf));
        if(len > 0){
            cout << "服務(wù)器say: " << buf << endl;
        } else if (len == 0){
            cout << "服務(wù)器端斷開(kāi)了連接" << endl;
            break;
        } else {
            perror("read");
            break;
        }
        sleep(1);
    }
    close(fd);
    return 0;
}

代碼測(cè)試圖示:

  1. 服務(wù)器先開(kāi)始, 客戶端先結(jié)束

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

  1. 服務(wù)器端先開(kāi)始, 服務(wù)器端先結(jié)束

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++

套接字通信(附帶單線程TCP套接字通信代碼),linux,tcp/ip,網(wǎng)絡(luò),c++文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-810785.html

到了這里,關(guān)于套接字通信(附帶單線程TCP套接字通信代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(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)文章

  • UDP套接字的通信(實(shí)現(xiàn)英漢互譯/程序替換/多線程聊天室/Windows與Linux通信)

    UDP套接字的通信(實(shí)現(xiàn)英漢互譯/程序替換/多線程聊天室/Windows與Linux通信)

    我們?cè)诳蛻舳税l(fā)英文,服務(wù)端做翻譯工作,讓翻譯好的中文再次發(fā)給我們的客戶端,然后打印出來(lái)。 翻譯的操作 創(chuàng)建一個(gè)txt文件里面包含英漢互譯的數(shù)據(jù) dict.txt 對(duì)txt中的數(shù)據(jù)進(jìn)行操作 分割函數(shù) 將英漢通過(guò)冒號(hào)分開(kāi)。 將文件數(shù)據(jù)插入map里面 重新加載文件 通過(guò)捕捉2號(hào)(ctrl

    2024年02月11日
    瀏覽(17)
  • 網(wǎng)絡(luò)編程套接字應(yīng)用分享【Linux &C/C++ 】【UDP應(yīng)用 | TCP應(yīng)用 | TCP&線程池小項(xiàng)目】

    網(wǎng)絡(luò)編程套接字應(yīng)用分享【Linux &C/C++ 】【UDP應(yīng)用 | TCP應(yīng)用 | TCP&線程池小項(xiàng)目】

    目錄 前提知識(shí) 1. 理解源ip,目的ip和Macip 2. 端口號(hào) 3. 初識(shí)TCP,UDP協(xié)議 4.?網(wǎng)絡(luò)字節(jié)序 5. socket 編程 sockaddr類型? 一,基于udp協(xié)議編程? 1. socket——?jiǎng)?chuàng)建套接字 2. bind——將套接字強(qiáng)綁定? 3. recvfrom——接受數(shù)據(jù) 4. sendto——發(fā)出信息 ?遇到的問(wèn)題 (1. 云服務(wù)器中以及無(wú)法分配I

    2024年04月08日
    瀏覽(26)
  • TCP服務(wù)器(套接字通信)

    TCP服務(wù)器(套接字通信)

    服務(wù)器 ? ? 客戶端 ? ? 結(jié)果 ? ?

    2024年02月12日
    瀏覽(18)
  • C++網(wǎng)絡(luò)編程 TCP套接字基礎(chǔ)知識(shí),利用TCP套接字實(shí)現(xiàn)客戶端-服務(wù)端通信

    C++網(wǎng)絡(luò)編程 TCP套接字基礎(chǔ)知識(shí),利用TCP套接字實(shí)現(xiàn)客戶端-服務(wù)端通信

    流式套接字編程針對(duì)TCP協(xié)議通信,即是面向?qū)ο蟮耐ㄐ?,分為服?wù)端和客戶端兩部分。 1)加載套接字庫(kù)( 使用函數(shù)WSAStartup() ),創(chuàng)建套接字( 使用socket() ) 2)綁定套接字到一個(gè)IP地址和一個(gè)端口上( 使用函數(shù)bind() ) 3)將套接字設(shè)置為監(jiān)聽(tīng)模式等待連接請(qǐng)求( 使用函數(shù)

    2024年02月03日
    瀏覽(102)
  • 【網(wǎng)絡(luò)通信】socket編程——TCP套接字

    【網(wǎng)絡(luò)通信】socket編程——TCP套接字

    TCP依舊使用代碼來(lái)熟悉對(duì)應(yīng)的套接字,很多接口都是在udp中使用過(guò)的 所以就不會(huì)單獨(dú)把他們拿出來(lái)作為標(biāo)題了,只會(huì)把第一次出現(xiàn)的接口作為標(biāo)題 通過(guò)TCP的套接字 ,來(lái)把數(shù)據(jù)交付給對(duì)方的應(yīng)用層,完成雙方進(jìn)程的通信 在 tcpServer.hpp 中,創(chuàng)建一個(gè)命名空間 yzq 用于封裝 在命名

    2024年02月13日
    瀏覽(102)
  • Liunx 套接字編程(2)TCP接口通信程序

    Liunx 套接字編程(2)TCP接口通信程序

    面向連接、可靠傳輸、提供字節(jié)流傳輸服務(wù) 客戶端向服務(wù)器發(fā)送一個(gè)連接建立的請(qǐng)求流程,上圖中服務(wù)端第三步詳細(xì)流程 socket--創(chuàng)建套接字 bind---綁定 sockfd : socket返回的套接字描述符 addr: 要綁定的地址信息(不同地址域類型,有不同的地址結(jié)構(gòu)) listen--監(jiān)聽(tīng) 注意:listen第二

    2024年02月08日
    瀏覽(30)
  • 學(xué)習(xí)網(wǎng)絡(luò)編程N(yùn)o.5【TCP套接字通信】

    學(xué)習(xí)網(wǎng)絡(luò)編程N(yùn)o.5【TCP套接字通信】

    北京時(shí)間:2023/8/25/15:52,昨天剛把耗時(shí)3天左右的文章更新,充分說(shuō)明我們這幾天并不是在擺爛中度過(guò),而是在為了更文不懈奮斗,歷時(shí)這么多天主要是因?yàn)樵摬糠种R(shí)比較陌生,所以需要我們花費(fèi)大量的時(shí)間去細(xì)細(xì)研究,為后面無(wú)論是TCP套接字,還是網(wǎng)絡(luò)的學(xué)習(xí)都能更加融會(huì)

    2024年02月10日
    瀏覽(28)
  • Qt下Tcp套接字(socket)通信的整個(gè)流程

    Qt下Tcp套接字(socket)通信的整個(gè)流程

    QT += network Qt中提供的所有的Socket類都是非阻賽的 Qt中常用的用于socket通信的套接字類 ????????QTcpServer 用于TCP/IP通信,作為服務(wù)器端套接字使用 ????????QTcpSocket 用于TCP/IP通信,作為客戶端套接字使用。 ????????QUdpSocket 用于UDP通信,服務(wù)器,客戶端均使用此套接字

    2024年02月10日
    瀏覽(21)
  • Socket套接字編程(實(shí)現(xiàn)TCP和UDP的通信)

    Socket套接字編程(實(shí)現(xiàn)TCP和UDP的通信)

    ? ??????點(diǎn)進(jìn)來(lái)你就是我的人了 博主主頁(yè):??????戳一戳,歡迎大佬指點(diǎn)! 人生格言: 當(dāng)你的才華撐不起你的野心的時(shí)候,你就應(yīng)該靜下心來(lái)學(xué)習(xí)! 歡迎志同道合的朋友一起加油喔 ?????? 目標(biāo)夢(mèng)想:進(jìn)大廠,立志成為一個(gè)牛掰的Java程序猿,雖然現(xiàn)在還是一個(gè)??嘿嘿 謝謝

    2024年02月03日
    瀏覽(29)
  • 【C/C++套接字編程】TCP協(xié)議通信的簡(jiǎn)單實(shí)現(xiàn)

    目錄 前言 一、TCP_Server.cpp 二、TCP_Client.cpp 三、TCP Server.cpp (多線程) 總結(jié) 系列博客 【C/C++套接字編程】套接字的基本概念與基礎(chǔ)語(yǔ)法_Mr_Fmnwon的博客-CSDN博客 【C/C++套接字編程】TCP通信實(shí)驗(yàn)_Mr_Fmnwon的博客-CSDN博客 【C/C++套接字編程】UDP協(xié)議通信的簡(jiǎn)單實(shí)現(xiàn)_Mr_Fmnwon的博客-CSDN博

    2024年02月09日
    瀏覽(22)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包