網絡編程之TCP編程

基于? C/S :客戶端(client)/服務器端(server)

1.流程

? ? ? ?

2.? 函數接口

所有函數所需頭文件:

#include <sys/types.h> 
#include <sys/socket.h>

系統定義好了用來存儲網絡信息的結構體

ipv4通信使用的結構體:struct sockaddr_in

我們只需要直接定義結構體變量即可

2.1 創建套接字socket()

int socket(int domain, int type, int protocol);
功能:創建套接字
參數:domain:協議族AF_UNIX, AF_LOCAL  本地通信AF_INET            ipv4AF_INET6            ipv6type:套接字類型SOCK_STREAM:流式套接字SOCK_DGRAM:數據報套接字SOCK_RAW:原始套接字protocol:協議  一般填0 自動匹配底層 根據type系統默認自動幫助匹配對應協議傳輸層:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP網絡層:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)返回值:成功 文件描述符-- > sockfd (用于連接)失敗 -1,更新errno

?注意:TCP服務器端有兩類文件描述符 !!!
? ? ? ? 一類用于連接的文件描述符(sockfd-->socket函數返回值) 只有一個
? ? ? ? 一類用于通信的文件描述符(acceptfd-->accept函數返回值) 可以多個

2.2綁定套接字bind()

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:綁定
參數:socket:套接字addr:用于通信結構體 (提供的是通用結構體,需要根據選擇通信方式,填充對應結構體-通信當時socket第一個參數確定)   addrlen:結構體大小   
返回值:成功 0   失敗-1,更新errno

由于系統定義好的記錄網絡信息的結構體是struct sockaddr_in類型,因此,bind第二個參數使用時結構體變量地址的時候要強制類型轉換

2.3監聽listen()

int listen(int sockfd, int backlog);
功能:監聽,將主動套接字變為被動套接字
參數:sockfd:套接字backlog:(目前已無具體作用,寫個正數即可)同時響應客戶端請求鏈接的最大個數,不能寫0.不同平臺可同時鏈接的數不同,一般寫6-8個(隊列1:保存正在連接)(隊列2,連接上的客戶端)返回值:成功 0   失敗-1,更新errno 

注意:listen作用:主動套接字變為被動套接字!!!

2.4接收客戶端連接請求 accept()

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept(sockfd,NULL,NULL);
功能:阻塞函數,阻塞等待客戶端的連接請求,如果有客戶端連接,
則accept()函數返回,返回一個用于通信的套接字文件描述符;
參數:Sockfd :套接字addr: 鏈接客戶端的ip和端口號如果不需要關心具體是哪一個客戶端,那么可以填NULL;addrlen:結構體的大小如果不需要關心具體是哪一個客戶端,那么可以填NULL;
返回值: 成功:文件描述符; //用于通信失敗:-1,更新errno

2.5接受消息recv()

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能: 接收數據 
參數: sockfd: acceptfd ;buf  存放位置len  大小flags  一般填0,相當于read()函數MSG_DONTWAIT  非阻塞
返回值: < 0  失敗出錯  更新errno==0  表示客戶端退出>0   成功接收的字節個數

2.6發送消息send()

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:發送數據
參數:sockfd:socket函數的返回值buf:發送內容存放的地址len:發送內存的長度flags:如果填0,相當于write();

2.7連接服務器connect()

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:用于連接服務器;
參數:sockfd:socket函數的返回值addr:填充的結構體是服務器端的;addrlen:結構體的大小
返回值 -1 失敗,更新errno正確 0 

2.8 關閉套接字 close()

即關閉套接字文件

close(文件描述符);

3.服務器端

?按照流程:

(1)創建流式套接字socket()

? ? ?

(2)指定網絡信息

?(3)綁定套接字bind()

(4) 監聽listen()

(5) 等待客戶連接信息accept()

?注意:

在服務器端使用客戶的網絡信息時:

(6)收發消息 send() recv()

(7) 關閉套接字

源代碼:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>//  $$ 服務器端 $$  int main(int argc, char const *argv[])
{/*創建流式套接字*/int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err");return -1;}else{printf("創建套接字成功\n");}/*指定服務器網絡信息 使用的協議族(IPv4-->AF_INET)、IP地址、端口號等*/// 服務器的網絡信息通過一個系統定義好的結構體來描述struct sockaddr_in saddr;                     // 定義一個結構體變量saddr.sin_family = AF_INET;                   // 確定協議族-->IPv4saddr.sin_port = htons(atoi(argv[1]));        // 確定使用的端口號saddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 確定服務器IP地址/*綁定套接字*/int t1 = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));if (t1 < 0){perror("bind err");return -1;}else{printf("綁定套接字成功\n");}/*監聽*/int t2 = listen(sockfd, 6); // 將默認的主動套接字變為被動套接字if (t2 < 0){printf("listen err");return -1;}else{printf("監聽中\n");}int acceptfd;char buf[128] = "";int ret;// 定義一個結構體變量來存接收到的客戶信息struct sockaddr_in caddr;int len = sizeof(caddr); // len是記錄客戶信息的結構體的大小while (1){/*阻塞等待接收客戶端的連接請求,并將連接成功的客戶端信息寫入到結構體變量caddr中*/acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);if (acceptfd < 0){printf("accept err");return -1;}else{printf("等待接收客戶端請求\n");}printf("客戶IP:%s 端口號:%d \n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));while (1){/*接收消息*/ret = recv(acceptfd, buf, 128, 0); // 0-->相當于read(acceptfd,buf,128)if (ret < 0){perror("recv err");return -1;}else if (ret == 0){printf("客戶退出\n");break;}else{printf("%s 接收成功\n", buf);memset(buf, 0, sizeof(buf));}}close(acceptfd);}/* 關閉套接字 */close(sockfd);return 0;
}

4.客戶端

按照流程:

(1)創建流式套接字socket()

(2)指定服務器網絡信息

(3)連接服務器connect()

(4)發送接受消息 send()? recv()

(5)關閉套接字

源代碼:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
//  $$ 客戶端 $$  int main(int argc, char const *argv[])
{/*創建流式套接字*/int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err");return -1;}else{printf("創建套接字成功\n");}/*指定服務器的網絡信息*/struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr(argv[2]);/* 請求連接服務器*/int t = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));if (t < 0){perror("connect err");return -1;}else{printf("connect success\n");}char buf[128] = "";/* 發送消息 */while (1){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n'){buf[strlen(buf) - 1] = '\0';}if (strcmp(buf, "quit") == 0){break;}send(sockfd, buf, sizeof(buf), 0); // 0-->相當于write(sockfd,buf,sizeof(buf))}/* 關閉套接字 */close(sockfd);return 0;
}

5.TCP粘包問題

tcp粘包

tcp拆包

6.三次握手四次揮手

三次握手建立連接

第一次握手:客戶通過調用connect進行主動打開(active open)。這引起客戶TCP發送一個SYN(表示同步)分節(SYN=J),它告訴服務器客戶將在連接中發送數據的初始序列號。并進入SYN_SEND狀態,等待服務器的確認。

第二次握手:服務器必須確認客戶的SYN,同時自己也得發送一個SYN分節,它含有服務器將在同一連接中發送的數據的初始序列號。服務器以單個字節向客戶發送SYN和對客戶SYN的ACK(表示確認),此時服務器進入SYN_RECV狀態。

第三次握手:客戶收到服務器的SYN+ACK。向服務器發送確認分節,此分節發送完畢,客戶服務器進入ESTABLISHED狀態,完成三次握手。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83610.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

各個布局的區別以及示例

各個布局的區別以及示例 在前端開發中&#xff0c;常見的布局方式主要有以下幾種&#xff0c;每種布局都有其適用場景和特點&#xff1a; 1. 普通文檔流&#xff08;Normal Flow&#xff09; 特點&#xff1a;默認布局方式&#xff0c;元素按照HTML順序依次排列。適用場景&am…

性能優化 - 理論篇:常見指標及切入點

文章目錄 引言一、 Java 性能優化的核心思路二、為什么要度量&#xff1f;三、常用性能衡量指標詳解3.1 吞吐量與響應速度3.2 響應時間的具體度量&#xff1a;平均響應時間與百分位數3.3 并發量3.4 秒開率&#xff08;頁面秒開&#xff09;3.5 正確性&#xff08;功能可用性&am…

第2講、Odoo深度介紹:開源ERP的領先者

一、Odoo深度介紹&#xff1a;開源ERP的領先者 Odoo&#xff0c;其前身為OpenERP&#xff0c;是一款在全球范圍內廣受歡迎的開源企業管理軟件套件。它不僅僅是一個ERP系統&#xff0c;更是一個集成了客戶關系管理&#xff08;CRM&#xff09;、電子商務、網站構建、項目管理、…

Telerik生態整合:Kendo UI for Angular組件在WinForms應用中的深度嵌入(一)

Telerik DevCraft包含一個完整的產品棧來構建您下一個Web、移動和桌面應用程序。它使用HTML和每個.NET平臺的UI庫&#xff0c;加快開發速度。Telerik DevCraft提供完整的工具箱&#xff0c;用于構建現代和面向未來的業務應用程序&#xff0c;目前提供UI for ASP.NET MVC、Kendo…

2025年6月4日收獲

Authorization Authorization是一種通用的、標準化的權限控制和認證的通用框架&#xff0c;它能夠使跨系統和跨域的身份驗證和授權管理更容易&#xff0c;使不同應用程序之間能夠更輕松地實現單點登錄&#xff08;SSO&#xff09;、用戶身份驗證和授權控制等。 在前端使用 axi…

實時數據湖架構設計:從批處理到流處理的企業數據戰略升級

企業數據處理架構正在經歷一場深刻的變革。從最初的數據倉庫T1批處理模式&#xff0c;到如今的實時流處理架構&#xff0c;這一演進過程反映了業務對數據時效性要求的不斷提升。 文章目錄 第一章&#xff1a;數據湖演進歷程與現狀分析 第二章&#xff1a;實時數據湖核心架構剖…

iptables實戰案例

目錄 一、實驗拓撲 二、網絡規劃 三、實驗要求 四、環境準備 1.firewall &#xff08;1&#xff09;配置防火墻各大網卡IP并禁用 firewall和selinux &#xff08;2&#xff09;打開firewall路由轉發 2.PC1&#xff08;內網&#xff09; &#xff08;1&#xff09;配置防…

macOS 連接 Docker 運行 postgres,使用navicat添加并關聯數據庫

下載 docker注冊一個賬號&#xff0c;登錄 Docker創建 docke r文件 mkdir -p ~/.docker && touch ~/.docker/daemon.json寫入配置&#xff08;全量替換&#xff09; {"builder": {"gc": {"defaultKeepStorage": "20GB",&quo…

docker離線鏡像下載

背景介紹 在某些網絡受限的環境中&#xff0c;直接從Docker Hub或其他在線倉庫拉取鏡像可能會遇到困難。為了在這種情況下也能順利使用Docker鏡像&#xff0c;我們可以提前下載好所需的鏡像&#xff0c;并通過離線方式分發和使用。 當前鏡像有&#xff1a;python-3.8-slim.ta…

Android 3D球形水平圓形旋轉,旋轉動態更換圖片

看效果圖 1、事件監聽類 OnItemClickListener&#xff1a;3D旋轉視圖項點擊監聽器接口 public interface OnItemClickListener {/*** 當旋轉視圖中的項被點擊時調用** param view 被點擊的視圖對象* param position 被點擊項在旋轉視圖中的位置索引&#xff08;從0開始&a…

48V帶極性反接保護-差共模浪涌防護方案

在工業自動化&#xff08;電動機驅動 / 工業機器人&#xff09;、交通基礎設施&#xff08;充電樁 / 車載電子&#xff09;、安防系統&#xff08;監控攝像頭 / 門禁&#xff09;、儲能設備&#xff08;BMS / 離網控制器&#xff09;等領域&#xff0c;DC48V 電源因安全特低電壓…

CentOS在vmware局域網內搭建DHCP服務器【踩坑記錄】

1. 重新設置環境 配置dhcp服務踩了不少坑&#xff0c;這里重頭搭建記錄一下&#xff1a; 1.1 centos 網卡還原 如果之前搭了亂七八糟的環境&#xff0c;導致NAT模式也沒法上網&#xff0c;這里重新還原 我們需要在NAT模式下聯網&#xff0c;下載DHCP服務 先把centos的網卡還…

《Docker》架構

文章目錄 架構模式單機架構應用數據分離架構應用服務器集群架構讀寫分離/主從分離架構冷熱分離架構垂直分庫架構微服務架構容器編排架構什么是容器&#xff0c;docker&#xff0c;鏡像&#xff0c;k8s 架構模式 單機架構 單機架構其實就是應用服務器和單機服務器都部署在同一…

Web3時代的數據保護挑戰與應對策略

隨著互聯網技術的飛速發展&#xff0c;我們正步入Web3時代&#xff0c;這是一個以去中心化、用戶主權和數據隱私為核心的新時代。然而&#xff0c;Web3時代也帶來了前所未有的數據保護挑戰。本文將探討這些挑戰&#xff0c;并提出相應的應對策略。 數據隱私挑戰 在Web3時代&a…

從零打造算法題刷題助手:Agent搭建保姆級攻略

我用Trae 做了一個有意思的Agent 「大廠機試助手」。 點擊 https://s.trae.com.cn/a/d2a596 立即復刻&#xff0c;一起來玩吧&#xff01; Agent 簡介 Agent名稱為大廠機試助手&#xff0c;主要功能有以下三點。 解題&#xff1a; 根據用戶給出的題目給出具體的解題思路引導做…

【JavaWeb】MVC三層架構

MVC三層架構 MVC 是什么&#xff1f;三層架構的組成&#xff08;View、Controller、Model&#xff09;各層職責劃分示例說明面試高頻問題與參考答案 MVC&#xff08;Model-View-Controller&#xff09;是一種經典的軟件設計模式&#xff0c;廣泛應用于 Web 應用開發中&#xf…

嵌入式分析利器:DuckDB與SqlSugar實戰

? 一、DuckDB 的核心特性與適用場景 DuckDB 是一款 嵌入式分析型數據庫&#xff08;OLAP&#xff09; &#xff0c;專為高效查詢設計&#xff0c;主要特點包括&#xff1a; 列式存儲與向量化引擎 數據按列存儲&#xff0c;提升聚合統計效率&#xff08;如 SUM/AVG&#xf…

React---day6、7

6、組件之間進行數據傳遞 **6.1 父傳子&#xff1a;**props傳遞屬性 父組件&#xff1a; <div><ChildCpn name"蔣乙菥" age"18" height"1,88" /> </div>子組件&#xff1a; export class ChildCpn extends React.Component…

Windows上用FFmpeg采集攝像頭推流 → MediaMTX服務器轉發流 → WSL2上拉流播放

1. Windows上 FFmpeg 推流&#xff08;攝像頭采集&#xff09; 設備名稱可用 ffmpeg -list_devices true -f dshow -i dummy 查詢&#xff0c;假設為Integrated Camera 采集推流示例&#xff08;推RTMP到MediaMTX&#xff09;&#xff1a; ffmpeg -rtbufsize 100M -f dshow …

SpringBoot1--簡單體驗

1 Helloworld 打開&#xff1a;https://start.spring.io/ 選擇maven配置。增加SpringWeb的依賴。 Generate之后解壓&#xff0c;代碼大致如下&#xff1a; hpDESKTOP-430500P:~/springboot2/demo$ tree ├── HELP.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── s…