Linux TCP 編程詳解與實例

一、引言

在網絡編程的領域中,TCP(Transmission Control Protocol)協議因其可靠的數據傳輸特性而被廣泛應用。在 Linux 環境下,使用 C 或 C++ 進行 TCP 編程可以實現各種強大的網絡應用。本文將深入探討 Linux TCP 編程的各個方面,包括 API 接口的詳細說明、TCP Server 和 TCP Client 的實例代碼,以及完整的測試流程。

二、TCP 編程的 API 接口說明

(一)socket() 函數

int socket(int domain, int type, int protocol);
  • 功能:創建一個套接字。
  • 參數:
    • domain:指定協議族,常見的有 AF_INET(IPv4 網絡協議)和 AF_INET6(IPv6 網絡協議)。
    • type:套接字類型,對于 TCP 通常使用 SOCK_STREAM
    • protocol:指定使用的具體協議,通常設置為 0 以使用默認的 TCP 協議。
  • 返回值:成功時返回一個非負的套接字描述符,失敗時返回 -1。

(二)bind() 函數

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 功能:將套接字與本地地址和端口綁定。
  • 參數:
    • sockfd:由 socket() 函數返回的套接字描述符。
    • addr:指向包含地址和端口信息的結構體,如 struct sockaddr_in(IPv4)或 struct sockaddr_in6(IPv6)。
    • addrlenaddr 結構體的長度。
  • 返回值:成功返回 0,失敗返回 -1。

(三)listen() 函數

int listen(int sockfd, int backlog);
  • 功能:將套接字設置為監聽狀態,準備接受客戶端的連接請求。
  • 參數:
    • sockfd:已綁定的套接字描述符。
    • backlog:指定等待連接隊列的最大長度。
  • 返回值:成功返回 0,失敗返回 -1。

(四)accept() 函數

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 功能:從已完成連接隊列中取出一個連接,并創建一個新的套接字與客戶端進行通信。
  • 參數:
    • sockfd:監聽套接字描述符。
    • addr:用于存儲客戶端的地址信息。
    • addrlen:用于指定 addr 結構體的長度。
  • 返回值:成功返回一個新的套接字描述符用于與客戶端通信,失敗返回 -1。

(五)connect() 函數(客戶端使用)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 功能:客戶端向服務器發起連接請求。
  • 參數:
    • sockfd:套接字描述符。
    • addr:指向服務器的地址結構體。
    • addrlenaddr 結構體的長度。
  • 返回值:成功返回 0,失敗返回 -1。

(六)send()recv() 函數

send() 函數
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 功能:用于發送數據。
  • 參數:
    • sockfd:套接字描述符。
    • buf:指向要發送數據的緩沖區。
    • len:要發送的數據長度。
    • flags:控制選項,通常設置為 0。
  • 返回值:成功返回實際發送的字節數,失敗返回 -1。
recv() 函數
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 功能:用于接收數據。
  • 參數:
    • sockfd:套接字描述符。
    • buf:用于存儲接收數據的緩沖區。
    • len:緩沖區的長度。
    • flags:控制選項,通常設置為 0。
  • 返回值:成功返回實際接收的字節數,失敗返回 -1。

(七)close() 函數

int close(int fd);
  • 功能:關閉套接字。
  • 參數:要關閉的套接字描述符。

三、TCP Server 實例代碼(支持多線程和回顯)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>#define MAX_CONNECTIONS 10  // 最大連接數量pthread_mutex_t connectionCountMutex;
int connectionCount = 0;  // 記錄當前連接數void *handle_client(void *arg) {int client_fd = *((int *)arg);char buffer[1024];int bytes_read;while ((bytes_read = recv(client_fd, buffer, sizeof(buffer), 0)) > 0) {// 回顯接收到的數據send(client_fd, buffer, bytes_read, 0);}// 處理客戶端斷開連接pthread_mutex_lock(&connectionCountMutex);connectionCount--;printf("Client disconnected. Current connections: %d\n", connectionCount);pthread_mutex_unlock(&connectionCountMutex);close(client_fd);pthread_exit(NULL);
}int main() {int server_fd, new_socket;struct sockaddr_in address;int addrlen = sizeof(address);int port = 8080;  // 服務器監聽的端口// 創建套接字if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}// 初始化地址結構體address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(port);// 綁定套接字到本地地址和端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("Bind failed");exit(EXIT_FAILURE);}// 開始監聽if (listen(server_fd, MAX_CONNECTIONS) < 0) {perror("Listen failed");exit(EXIT_FAILURE);}printf("Server is listening on port %d...\n", port);pthread_mutex_init(&connectionCountMutex, NULL);while (1) {// 接受客戶端連接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {perror("Accept failed");exit(EXIT_FAILURE);}printf("New connection accepted. Current connections: %d\n", ++connectionCount);// 檢查連接數是否達到上限if (connectionCount > MAX_CONNECTIONS) {printf("Reached maximum connections. Closing new connection.\n");close(new_socket);connectionCount--;continue;}pthread_t thread;if (pthread_create(&thread, NULL, handle_client, &new_socket)!= 0) {perror("Thread creation failed");close(new_socket);connectionCount--;continue;}// 分離線程,使其資源在結束時自動回收pthread_detach(thread);}// 清理pthread_mutex_destroy(&connectionCountMutex);// 關閉服務器套接字close(server_fd);return 0;
}

四、TCP Client 實例代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main(int argc, char *argv[]) {if (argc!= 3) {printf("Usage: %s <server_ip> <port>\n", argv[0]);return 1;}int sock = 0;struct sockaddr_in serv_addr;char buffer[1024] = {0};int port = atoi(argv[2]);  // 將命令行參數轉換為端口號char *server_ip = argv[1];  // 服務器 IP 地址// 創建套接字if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {printf("\n Socket creation error \n");return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(port);// 將服務器 IP 地址從字符串轉換為網絡地址格式if (inet_pton(AF_INET, server_ip, &serv_addr.sin_addr) <= 0) {printf("\nInvalid address/ Address not supported \n");return -1;}// 連接到服務器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {printf("\nConnection Failed \n");return -1;}printf("Connected to server\n");while (1) {printf("Enter message: ");fgets(buffer, sizeof(buffer), stdin);// 發送數據send(sock, buffer, strlen(buffer), 0);// 接收服務器響應int valread = recv(sock, buffer, 1024, 0);if (valread <= 0) {printf("Server disconnected\n");break;}printf("Received: %s", buffer);}// 關閉套接字close(sock);return 0;
}

五、測試驗證

使用 GCC 編譯器編譯服務器程序:

gcc server.c -o server -lpthread
./server

同樣使用 GCC 編譯器編譯客戶端程序:

gcc client.c -o client
  1. 運行客戶端程序,并傳入服務器的 IP 地址和端口作為參數,例如:
./client 127.0.0.1 8080

在這里插入圖片描述

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

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

相關文章

原生redis實現分布式鎖

用 原生 Redis&#xff08;Jedis、Lettuce&#xff09; 實現分布式鎖&#xff0c;可以參考 Redisson 的原理&#xff0c;但需要自己處理鎖的自動續期、故障恢復等細節。核心思路是使用 Redis 的 SET NX EX 或 SET PX NX 命令來實現互斥鎖&#xff0c;并利用 Lua 腳本 保障原子性…

論文筆記:Rethinking Graph Neural Networks for Anomaly Detection

目錄 摘要 “右移”現象 beta分布及其小波 實驗 《Rethinking Graph Neural Networks for Anomaly Detection》&#xff0c;這是一篇關于圖&#xff08;graph&#xff09;上異常節點診斷的論文。 論文出處&#xff1a;ICML 2022 論文地址&#xff1a;Rethinking Graph Ne…

神經網絡常見激活函數 6-RReLU函數

文章目錄 RReLU函數導函數函數和導函數圖像優缺點pytorch中的RReLU函數tensorflow 中的RReLU函數 RReLU 隨機修正線性單元&#xff1a;Randomized Leaky ReLU 函數導函數 RReLU函數 R R e L U { x x ≥ 0 a x x < 0 \rm RReLU \left\{ \begin{array}{} x \quad x \ge 0…

Vue(6)

一.路由板塊封裝 &#xff08;1&#xff09;路由的封裝抽離 目標&#xff1a;將路由板塊抽離出來 好處&#xff1a;拆分板塊&#xff0c;利于維護 // 路由的使用步驟 5 2 // 5個基礎步驟 // 1. 下載 v3.6.5 // 2. 引入 // 3. 安裝注冊 Vue.use(Vue插件) // 4. 創建路由對象…

【python】matplotlib(animation)

文章目錄 1、matplotlib.animation1.1、FuncAnimation1.2、修改 matplotlib 背景 2、matplotlib imageio2.1、折線圖2.2、條形圖2.3、散點圖 3、參考 1、matplotlib.animation 1.1、FuncAnimation matplotlib.animation.FuncAnimation 是 Matplotlib 庫中用于創建動畫的一個…

【東莞常平】戴爾R710服務器不開機維修分享

1&#xff1a;2025-02-06一位老客戶的朋友剛開工公司ERP服務器一臺戴爾老服務器故障無法開機&#xff0c;于是經老客戶介紹找到我們。 2&#xff1a;服務器型號是DELL PowerEdge R710 這個服務器至少也有15年以上的使用年限了。 3&#xff1a;客戶反饋的故障問題為&#xff1a;…

Spring AI -使用Spring快速開發ChatGPT應用

前言 Spring在Java生態中一直占據大半江山。最近我發現Spring社區推出了一個Spring AI項目&#xff0c;目前該項目還屬于Spring實驗性項目&#xff0c;但是我們可以通過該項目&#xff0c;可以非常快速的開發出GPT對話應用。 本篇文章將會對SpringAI進行簡單的介紹和使用&#…

經典排序算法復習----C語言

經典排序算法復習 分類 交換類 冒泡快排 分配類 計數排序基數排序 選擇類 選擇排序 堆排序 歸并類 歸并排序 插入類 直接插入排序 希爾排序 折半插入排序 冒泡排序 基于交換。每一輪找最大值放到數組尾部 //冒泡排序 void bubSort(int* arr,int size){bool sorte…

BFS解決拓撲排序(3題)

目錄 拓撲排序 1.如何排序&#xff1f; 2.如何形成拓撲排序 3.如何建圖 1.看數據稠密度 2. 根據算法流程靈活建圖 1.課程表 2.課程表2 3.火星詞典 拓撲排序 找到做事情的先后順序&#xff0c;拓撲排序的結果可能不是唯一的 1.如何排序&#xff1f; 1.找出圖中入度為…

kafka 3.5.0 raft協議安裝

前言 最近做項目&#xff0c;需要使用kafka進行通信&#xff0c;且只能使用kafka&#xff0c;筆者沒有測試集群&#xff0c;就自己搭建了kafka集群&#xff0c;實際上筆者在很早之前就搭建了&#xff0c;因為當時還是zookeeper&#xff08;簡稱ZK&#xff09;注冊元數據&#…

Unity項目接入xLua的一種流程

1. 導入xlua 首先導入xlua&#xff0c;這個不用多說 2. 編寫C#和Lua交互腳本 基礎版本&#xff0c;即xlua自帶的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

四次揮手詳解

文章目錄 一、四次揮手各狀態FIN_WAIT_1CLOSE_WAITFIN_WAIT_2LAST_ACKTIME_WAITCLOSE 二、雙方同時調用close()&#xff0c;FIN_WAIT_1狀態后進入CLOSING狀態CLOSING狀態 三、TIME_WAIT狀態詳解(1) TIME_WAIT狀態下的2MSL是什么MSL &#xff08;報文最大生存時間&#xff09;為…

【嵌入式 Linux 音視頻+ AI 實戰項目】瑞芯微 Rockchip 系列 RK3588-基于深度學習的人臉門禁+ IPC 智能安防監控系統

前言 本文主要介紹我最近開發的一個個人實戰項目&#xff0c;“基于深度學習的人臉門禁 IPC 智能安防監控系統”&#xff0c;全程滿幀流暢運行。這個項目我目前全網搜了一圈&#xff0c;還沒發現有相關類型的開源項目。這個項目只要稍微改進下&#xff0c;就可以變成市面上目前…

java: framework from BLL、DAL、IDAL、MODEL、Factory using oracle

oracel 21c sql: -- 創建 School 表 CREATE TABLE School (SchoolId CHAR(5) NOT NULL,SchoolName NVARCHAR2(500) NOT NULL,SchoolTelNo VARCHAR2(8) NULL,PRIMARY KEY (SchoolId) );CREATE OR REPLACE PROCEDURE addschool(p_school_id IN CHAR,p_school_name IN NVARCHAR2,p…

解決錯誤:CondaHTTPError: HTTP 000 CONNECTION FAILED for url

解決錯誤&#xff1a;CondaHTTPError: HTTP 000 CONNECTION FAILED for url 查看channels:vim ~/.condarcshow_channel_urls: true channels:- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/…

Apache APISIX 快速入門

文章目錄 apisix 快速入門什么是apisix有了 NGINX 和 Kong&#xff0c;為什么還需要 Apache APISIX&#xff1f;軟件架構基于 Nginx 開源版本&#xff0c;而 Nginx 并不支持動態配置&#xff0c;為什么 Apache APISIX 聲稱自己可以實現動態配置&#xff1f; 安裝配置 APISIX配置…

2025嵌入式高頻面試題解析

一、概述 到了年初&#xff0c;是求職者最活躍的時間。本文梳理了嵌入式高頻面試題&#xff0c;幫助求職者更好地準備面試&#xff0c;同時也為技術愛好者提供深入學習嵌入式知識的參考。 二、C 語言基礎 2.1 指針與數組 問題 1&#xff1a;指針和數組的區別是什么&#xf…

1.攻防世界 baby_web

題目描述這里有提示&#xff0c;初始頁面 進入題目頁面如下 很簡潔的頁面只有一行HELLO WORLD ctrlu查看了源碼也沒有信息 用burp suite抓包&#xff0c;并發送到重放器 根據提示&#xff08;初始頁面&#xff09;修改訪問index.php文件 index.php index.php 是一種常見的…

什么是三層交換技術?與二層有什么區別?

什么是三層交換技術&#xff1f;讓你的網絡飛起來&#xff01; 一. 什么是三層交換技術&#xff1f;二. 工作原理三. 優點四. 應用場景五. 總結 前言 點個免費的贊和關注&#xff0c;有錯誤的地方請指出&#xff0c;看個人主頁有驚喜。 作者&#xff1a;神的孩子都在歌唱 大家好…

【機器學習】數據預處理之數據歸一化

數據預處理之數據歸一化 一、摘要二、數據歸一化概念三、數據歸一化實現方法3.1 最值歸一化方法3.2 均值方差歸一化方法 一、摘要 本文主要講述了數據歸一化&#xff08;Feature Scaling&#xff09;的重要性及其方法。首先通過腫瘤大小和發現時間的例子&#xff0c;說明了不同…