Linux 下 socket 編程介紹及 TCP 客戶端與服務端創建示例

目錄

    • socket 編程接口
    • TCP 服務端
    • TCP 客戶端
    • 更多內容

本文介紹了 Linux 下的 socket 編程,及總結了使用 socket 接口實現 TCP 服務端和客戶端的示例代碼。

socket 編程接口

  • socket() 函數:用于創建一個新的 socket 描述符:
int socket(int domain, int type, int protocol);

其中,domain 指定協議族(如 AF_INET 表示 IPv4),type 指定 socket 類型(如 SOCK_STREAM 表示 TCP,SOCK_DGRAM 表示 UDP),protocol 通常設置為 0,表示使用默認協議。

  • bind() 函數:將 socket 綁定到一個 IP 地址或端口上:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指針,包含了 IP 地址和端口號信息,addrlen 是 struct sockaddr 的大小。

  • listen() 函數:用于監聽一個 socket 上的連接請求:
int listen(int sockfd, int backlog);

其中,sockfd 是 socket 描述符,backlog 指定了等待連接的最大隊列長度。

  • accept() 函數:從監聽 socket 的等待隊列中接受一個連接:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

該函數返回一個新的 socket 描述符,用于與客戶端進行通信,addr 和 addrlen 用于獲取客戶端的地址信息。

  • connect() 函數:用于建立一個到服務器的連接:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指針,包含了服務器的 IP 地址和端口號信息。

  • send() 和 recv() 函數:用于通過 socket 發送和接收數據:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

其中,sockfd 是 socket 描述符,buf 是指向數據緩沖區的指針,len 是緩沖區的大小,flags 是控制函數行為的標志。

  • close() 函數:用于關閉一個 socket:
int close(int sockfd);

其中,sockfd 是 socket 描述符。

  • 在 Linux 下進行 socket 編程時,通常還需要處理錯誤和異常情況,以及進行地址轉換(使用 inet_ntop 和 inet_pton 函數)和字節序轉換(使用 htons 和 ntohs 函數)等操作。

TCP 服務端

  • tcp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <errno.h>
#include "tcp_server.h"char buffer[BUFFER_SIZE] = {0};int server_init_socket(void) 
{int socket_fd;struct sockaddr_in address;if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(socket_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}if (listen(socket_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}return socket_fd;
}int server_set_socket_timeout(int socket_fd, long milliseconds)
{struct timeval tv;tv.tv_sec =  milliseconds / 1000; tv.tv_usec = (milliseconds % 1000) * 1000;if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0) {perror("setsockopt SO_RCVTIMEO");exit(EXIT_FAILURE);}return 0;
}int server_accept_client(int socket_fd) 
{struct sockaddr_in address;int addrlen = sizeof(address);int temp_fd = accept(socket_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (temp_fd < 0) {perror("accept");exit(EXIT_FAILURE);}printf("Connection established with %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));return temp_fd;
}int server_receive_data(int socket_fd, char *message, ssize_t *size) 
{ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0);if (bytes_received == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ETIMEDOUT){printf("socket recv time out \r\n");return 1;} else {perror("recv");exit(EXIT_FAILURE);}}*size = bytes_received;return 0;
}void server_send_data(int socket_fd, const char *message, ssize_t size) 
{if (send(socket_fd, message, size, 0) < 0) {perror("send");exit(EXIT_FAILURE);}
}int server_check_tcp_connection(int socket_fd) 
{int error = 0;socklen_t len = sizeof(error);if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {if (error == 0) {return 1;}}return 0;
}int server_close_socket(int socket_fd) 
{close(socket_fd);return 0;
}
  • tcp_server.h
#ifndef __TCP_SERVER__
#define __TCP_SERVER__#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024extern char buffer[BUFFER_SIZE];int server_init_socket(void);
int server_accept_client(int socket_fd);
int server_set_socket_timeout(int socket_fd, long milliseconds);
int server_receive_data(int socket_fd, char *message, ssize_t *size) ;
void server_send_data(int socket_fd, const char *message, ssize_t size);
int server_check_tcp_connection(int socket_fd);
int server_close_socket(int fd);#endif
  • main.c
#include <stdio.h>
#include "tcp_server.h"int main(void)
{int server_fd, client_fd;char recv_buffer[1024];ssize_t size = 0;server_fd = server_init_socket();client_fd = server_accept_client(server_fd);server_send_data(client_fd, "Hello TCP!", 10);server_receive_data(client_fd, recv_buffer, &size);printf("%s", recv_buffer);return 0;
}

TCP 客戶端

  • tcp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>#include "tcp_client.h"int client_init_socket(void)
{int socket_fd;struct sockaddr_in server_address;if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = inet_addr(SERVER_IP);server_address.sin_port = htons(SERVER_PORT);if (connect(socket_fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {perror("connect");exit(EXIT_FAILURE);}return socket_fd;
}int client_receive_data(int socket_fd, char *message, ssize_t *size) 
{ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0);if (bytes_received == -1) {perror("recv");exit(EXIT_FAILURE);}*size = bytes_received;return 0;
}void client_send_data(int socket_fd, const char *message, ssize_t size) 
{if (send(socket_fd, message, size, 0) < 0) {perror("send");exit(EXIT_FAILURE);}
}int client_check_tcp_connection(int socket_fd) 
{int error = 0;socklen_t len = sizeof(error);if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {if (error == 0) {return 1;}}return 0;
}int client_close_socket(int socket_fd)
{close(socket_fd);return 0;
}
  • tcp_client.h
#ifndef __TCP_CLIENT_H__
#define __TCP_CLIENT_H__#include <sys/socket.h>#define SERVER_IP "192.168.0.123"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int client_init_socket(void);
int client_receive_data(int socket_fd, char *message, ssize_t *size);
void client_send_data(int socket_fd, const char *message, ssize_t size);
int client_check_tcp_connection(int socket_fd);
int client_close_socket(int socket_fd);#endif
  • main.c
#include <stdio.h>
#include "tcp_client.h"int main(void)
{int client_fd = 0;char buffer[1024];ssize_t size = 0;client_fd = client_init_socket();client_send_data(client_fd, "Hello TCP!", 10);client_receive_data(client_fd, buffer, &size);printf("%s", recv_buffer);return 0;
}

更多內容

  • CSDN博客:@Hello阿爾法
  • 嗶哩嗶哩:@Hello阿爾法
  • 知乎:@Hello阿爾法

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

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

相關文章

Linux內核MMC框架

1.mmc的概念 1.MMC MultiMedia Card&#xff0c;多媒體存儲卡&#xff0c; 但后續泛指一個接口協定&#xff08;一種卡式&#xff09;&#xff0c;能符合這接口的內存器都可稱作mmc儲存體,工作電壓&#xff1a;高電壓為2.7&#xff5e;3.6 V&#xff0c;低電壓為1.65&#xf…

【微服務】微服務中常用認證加密方案總結

目錄 一、前言 二、登錄認證安全問題 3.1 認證方式選擇 三、常用的加密方案 3.1 MD5加密算法 3.1.1 md5特點 3.1.2 md5原理 3.1.3 md5使用場景 3.2 AES加密算法 3.2.1 AES簡介 3.2.2 AES加解原理 3.2.3 AES算法優缺點 3.2.4 AES算法使用場景 3.3 RSA加密算法 3.3…

Flutter Dio進階:使用Flutter Dio攔截器實現高效的API請求管理和身份驗證刷新

Flutter筆記 使用Flutter Dio攔截器實現高效的API請求管理和身份驗證刷新 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article…

金融業被網絡攻擊了怎么辦,如何治理和風險控制?

近年來&#xff0c;網絡罪犯的人數和復雜程度都在增加&#xff0c;網絡罪犯的目標鎖定變得更具策略性&#xff0c;更加專注于最大效率和獲利。隨著有關全球網絡犯罪的數據持續涌入&#xff0c;可以看出金融服務企業已然成為頭號鎖定目標。雖然金融服務企業在網絡安全人員、工具…

圖論例題解析

1.圖論基礎概念 概念 &#xff08;注意連通非連通情況&#xff0c;1節點&#xff09; 無向圖&#xff1a; 度是邊的兩倍&#xff08;沒有入度和出度的概念&#xff09; 1.完全圖&#xff1a; 假設一個圖有n個節點&#xff0c;那么任意兩個節點都有邊則為完全圖 2.連通圖&…

【MySQL】SQL 優化

MySQL - SQL 優化 1. 在 MySQL 中&#xff0c;如何定位慢查詢&#xff1f; 1.1 發現慢查詢 現象&#xff1a;頁面加載過慢、接口壓力測試響應時間過長&#xff08;超過 1s&#xff09; 可能出現慢查詢的場景&#xff1a; 聚合查詢多表查詢表數據過大查詢深度分頁查詢 1.2 通…

錯誤筆記:Anaconda 錯誤(閃退、無法安裝等) + Pycharm 錯誤(無法啟動)+ python 報錯

Anaconda 錯誤 1、導航器啟動中發生-- 閃退 方法一&#xff1a; Windows下&#xff1a; 1&#xff09;使用管理員運行&#xff1a;conda prompt 2&#xff09;執行命令 conda update anaconda-navigator 方法二&#xff1a; 重置Anaconda配置&#xff1a;anaconda-navigator…

C語言第三十四彈---動態內存管理(下)

?個人主頁&#xff1a; 熬夜學編程的小林 &#x1f497;系列專欄&#xff1a; 【C語言詳解】 【數據結構詳解】 動態內存管理 1、動態內存經典筆試題分析 1.1、題目1 1.2、題目2 1.3、題目3 1.4、題目4 2、柔性數組 2.1、柔性數組的特點 2.2、柔性數組的使用 2.3、…

【c++】計算樹的深度和節點數

在C語言中&#xff0c;計算給定樹的層數&#xff08;深度&#xff09;和節點總數通常需要使用遞歸方法。首先&#xff0c;我們需要定義樹的節點結構。這里假設我們處理的是一棵二叉樹&#xff0c;每個節點有兩個子節點&#xff08;左子節點和右子節點&#xff09;。 下面是一個…

5.STL源碼解析-算法、仿函數、適配器

算法 STL算法總覽 仿函數與適配器 C標準模板庫&#xff08;STL&#xff09;是C程序員的得力工具&#xff0c;提供了許多強大而高效的數據結構和算法。在STL中&#xff0c;仿函數&#xff08;Functor&#xff09;和適配器&#xff08;Adapter&#xff09;是兩個重要的概念…

C語言文件操作(fputs() 和 puts() 有兩個小區別)

fputs() 和 puts() 有兩個小區別&#xff1a; 1.puts() 只能向標準輸出流輸出&#xff0c;而 fputs() 可以向任何流輸出。 2.使用 puts() 時&#xff0c;系統會在自動在其后添加換行符&#xff1b;而使用 fputs() 時&#xff0c;系統不會自動添加換行符。 那么這是不是意味著使…

【C++精簡版回顧】17.io流,流中提供的函數

1.流含義 2.流類 3.流對象 4.流對象的函數 舉例&#xff1a; 要求&#xff1a;數據結構中經常需要對齊輸出數據&#xff0c;應該怎么做&#xff1f; 1.頭文件 #include<iomanip> 2.創建表格頭 cout << setiosflags(ios::left) << setw(8) << "姓名…

BUGKU 網站被黑

打開環境&#xff0c;什么都沒發現&#xff0c;使用蟻劍掃描一下&#xff0c;發現shell.php&#xff0c;打開 使用BP抓包&#xff0c;進行爆破 得到密碼&#xff1a;hack 進去得到flag

GEE高階應用python wxee——如何利用來自 GOES-16 和 MODIS 的數據來可視化火災隨時間的進展分析

火災進展 wxee 是專為處理氣象數據而設計的,但它對遙感數據也很有用。在本示例中,我們將了解 wxee 如何利用來自 GOES-16 和 MODIS 的數據來可視化火災隨時間的進展情況。 安裝和設定 #!pip install wxeeimport ee import wxeeee.Authenticate() wxee.Initialize(project=x…

每日一類:QLabel深入解析

QLabel是Qt中用于顯示文本或圖像的控件&#xff0c;屬于Qt Widgets模塊。它是展示靜態內容的理想選擇&#xff0c;支持富文本格式&#xff0c;使得文本可以包含不同的字體、顏色和鏈接。QLabel也可以用來顯示圖像&#xff0c;包括動態圖像。此外&#xff0c;它還支持文本和圖像…

【Java面試題】SpringBoot與Spring的區別

主要區別體現幾個方面&#xff1a; 1.操作簡便性 SpringBoot提供極其快速和簡化的操作&#xff0c;使得Spring開發者能更快速上手。它通過提供spring的運行配置&#xff0c;以及為通用spring項目提供許多非功能性特性&#xff0c;進一步簡化了開發過程。 2.框架擴展性 Spri…

算法學習——差分

在了解差分之前&#xff0c;我們首先需要知道前綴和的概念。 前綴和簡單介紹&#xff1a; 對于一個數組A&#xff0c;要求出A[0]~A[i]的和&#xff0c;我們通常的做法是遍歷一邊&#xff0c;加起來。但是要求m組這樣的和&#xff0c;我們就要花費O(mn)的時間復雜度。顯然不合…

【考研數學】湯家鳳1800題什么水平?

我覺得湯家鳳基礎武忠祥強化這個組合非常的不錯 湯家鳳老師的講課風格 湯家鳳老師的基礎課程是大家公認的講的詳細&#xff0c;并且非常照顧基礎不好的學生&#xff0c;會把基礎知識點掰開揉碎的講給大家聽&#xff0c;在上課過程中&#xff0c;還會把知識點寫在A4紙上&#…

試了下新型的360AI搜索

360AI搜索 試了下&#xff0c;感覺還是挺不錯的。 比如問這個問題&#xff1a; ERROR 1698 (28000): Access denied for user rootlocalhost 它的回答&#xff1a; 對于ERROR 1698 (28000): Access denied for user rootlocalhost的問題&#xff0c;這通常是由于MySQL密碼為…

【Javascript】設計模式之單例模式

文章目錄 1、實現單例模式2、透明的單例模式3、用代理實現單例模式4、JavaScript 中的單例模式5、惰性單例6、通用的惰性單例7、小結 定義&#xff1a; 保證一個類僅有一個實例&#xff0c;并提供一個訪問它的全局訪問點 單例模式是一種常用的模式&#xff0c;有一些對象我們往…