網路編程練習題---利用TCP協議完成客戶端與服務端點對點通信

来源:https://www.cnblogs.com/fly-home/p/18233736
-Advertisement-
Play Games

目錄題目一解析代碼實現題目二:解析代碼實現tcp_client.ctcp_server.c 題目一 設計程式實現解析www.baidu.com的功能變數名稱,把獲取到的百度的IP地址全部輸出到終端並驗證是否正確。 解析 主機打算響應某個網站的網路請求,但是只知道網站功能變數名稱是無法通信的,需要對功能變數名稱進行地址解析, ...


目錄

題目一

設計程式實現解析www.baidu.com的功能變數名稱,把獲取到的百度的IP地址全部輸出到終端並驗證是否正確。

解析

主機打算響應某個網站的網路請求,但是只知道網站功能變數名稱是無法通信的,需要對功能變數名稱進行地址解析,得到網站的公有IP地址,所以Linux系統提供了名稱叫做gethostbyname()的函數介面實現該功能,使用規則如下:

image

代碼實現

/********************************************************************************
*
*	file name:	demo_domain.c
*	author	 :  [email protected] 
*	date	 :  2024/06/04
*	function :  
*               設計程式實現解析www.baidu.com的功能變數名稱,
*               把獲取到的百度的IP地址全部輸出到終端並驗證是否正確。
* 	note	 :  
*               1.可以通過ping 百度功能變數名稱,觀察返回值的IP地址來驗證獲取值是否正確
*               2.通過命令行輸入不同的功能變數名稱,來獲取不同功能變數名稱的IP地址
*                 例如:./xxx xxx(有效功能變數名稱地址)
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* ******************************************************************************/
/****************************頭文件*********************************************/
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    //對參數進行錯誤處理
    if(argc != 2)
    {
        fprintf(stderr, "argc error, errno: %d, %s\n", errno, strerror(errno));
        exit(1);
    }

    //利用gethostbyname函數介面,獲取目標功能變數名稱所包含的信息
    struct hostent *hostent =  gethostbyname(argv[1]);

    //定義一個結構體變數,用於存儲IP地址
    struct in_addr ip_hostent;
    //定義一個迴圈數組下標
    int i = 0;

    //迴圈將獲取得到的hostent結構體中的ip地址轉換為點分十進位字元串輸出
    while(hostent->h_addr_list[i] != NULL)
    {
        //將獲取IP地址進行類型轉換,存儲在ip_hostent中
        ip_hostent.s_addr = *(uint32_t *)(hostent->h_addr_list[i]);

        //利用函數介面inet_ntoa(),將網路節序類型轉換為點分十進位字元串類型並輸出
        printf("%s ip :%s\n", argv[1], inet_ntoa(ip_hostent));

        //對數組下標進行偏移
        i++;
    }

    return 0;
}

題目二:

利用TCP協議,設計兩個程式,一個作為客戶端,先發送連接申請給服務端,發送消息給服務端;另一個作為服務端,接受客戶端申請,並接受客戶端發送的消息。

解析

  1. listen函數不具有阻塞特性,因為listen只是相當於把socket的屬性更改為被動連接,可以接收其他進程的連接,設置好後便會返回,監聽的實質有操作系統完成。
  2. 調用listen函數需要設置監聽隊列的最大容量,該監聽隊列容量不是指的是服務端能連接客戶端的數量。
  3. accept函數具有阻塞特性,調用一次accept只能接收一個客戶端申請請求,並且會生成返回一個新的、專屬於當前連接的客戶端的文件描述符,該描述符一定要存儲起來,方便服務端後續與客戶端點對點通信。

代碼實現

tcp_client.c

/********************************************************************************
*
*	file name:	tcp_client.c
*	author	 :  [email protected] 
*	date	 :  2024/06/05
*	function :  該案例是掌握TCP協議通信方式,該代碼文件將實現客戶端發送信息給服務端的功能。
* 	note	 :  
*				1. 需要註意的是connect是非阻塞特性,所以一定要接收返回值進行判斷,
*				   否則會出現沒有連接成功,卻進入發送的錯誤狀態。
*				2. 由於該函數部分參數由命令行傳入,所以在執行文件時要加上參數
*				   例如:./xxx  xxx(埠號) xxx.xxx.xxx.xxx(服務端IP地址--點分十進位)
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* ******************************************************************************/
/****************************頭文件*********************************************/
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc,const char *argv[])
{
	//判斷命令行參數
	if(argc != 3)
	{
		fprintf(stderr, "argc error,errno:%d,%s\n",errno,strerror(errno));
		exit(1);
	}

	//創建TCP的套接字文件
	int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(tcp_socket == -1)
	{
		fprintf(stderr, "tcp socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(2);
	}

	//綁定本地信息--如果只打算實習發送功能,該步驟也可以省略
	struct sockaddr_in  host_addr;

	host_addr.sin_family 		= AF_INET; 						//協議族,為固定巨集
	host_addr.sin_port   		= htons(atoi(argv[1]));			//想要接收信息進程的埠號
	host_addr.sin_addr.s_addr   = htonl(INADDR_ANY);			//本地地址,填寫該巨集定義代表任意網口都可以接收值

	bind(tcp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));

	//向目標主機發送消息,需要設置目標埠和目標地址
	char buf[128] = {0};

	struct sockaddr_in  dest_addr;
	socklen_t flag_dest = sizeof(dest_addr);

	dest_addr.sin_family 		= AF_INET; 						//協議族,是固定的
	dest_addr.sin_port   		= htons(atoi(argv[1]));			//伺服器運行進程的埠號,必須轉換為網路位元組序
	dest_addr.sin_addr.s_addr   = inet_addr(argv[2]);			//要發送對象的IP地址,必須轉換為點分十進位字元串形式

	//使用connect函數介面向伺服器發起連接申請
	int flag_connect = connect(tcp_socket, (struct sockaddr *)&dest_addr, flag_dest);
	if(flag_connect == -1)
	{
		fprintf(stderr, "connect socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(3);
	}

	//迴圈向伺服器發送消息
	while(1)
	{
		//從鍵盤獲取信息
		scanf("%s", buf);
		write(tcp_socket, buf, strlen(buf));
		bzero(buf, sizeof(buf));
	}

	return 0;
}

tcp_server.c

/********************************************************************************
*
*	file name:	tcp_server.c
*	author	 :  [email protected] 
*	date	 :  2024/06/17
*	function :  該案例是掌握進行模塊化編程思想,以及封裝函數介面流程
* 	note	 :  
*				1. 需要註意的是listen是非阻塞特性,accept才具有阻塞特性
*				2. accpet在成功連接客戶端後,會重新創建一個新的、專屬於連接客戶端的
*				   套接字文件描述符,方便服務端與客戶端點對點通信
*				3. 由於該函數部分參數由命令行傳入,所以在執行文件時要加上參數
*				   例如:./xxx  xxx(埠號)
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* ******************************************************************************/
/****************************頭文件*********************************************/
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
	//對命令行傳入參數數量進行判斷
	if(argc != 2)
	{
		fprintf(stderr, "argc error,errno:%d,%s\n",errno,strerror(errno));
		exit(1);
	}

	//1.創建TCP套接字
	int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (tcp_socket == -1)
	{
		fprintf(stderr, "tcp socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(2);
	}

	//2.綁定自身的IP地址和埠,由於該處伺服器功能是接受信息,所以一定要綁定自身信息
	struct sockaddr_in  host_addr;

	host_addr.sin_family 		= AF_INET; 						//協議族,是固定的
	host_addr.sin_port   		= htons(atoi(argv[1]));			//目標埠,必須轉換為網路位元組序
	host_addr.sin_addr.s_addr   = htonl(INADDR_ANY);		    //目標地址  INADDR_ANY 這個巨集是一個整數,所以需要使用htonl轉換為網路位元組序

	bind(tcp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));

	//3.設置監聽,且監聽隊列最大容量設置為5
	listen(tcp_socket,5);

	//4.等待接受客戶端的連接請求
	struct sockaddr_in  client;
	socklen_t client_len = sizeof(client);

	//調用accept函數介面後,一定要接收其返回值,因為該返回值為accept創建的新的、專屬於連接客戶端的套接字文件描述符
	int connect_fd = accept(tcp_socket,(struct sockaddr *)&client,&client_len); //會阻塞
	char buf[128] = {0};

	//5.說明雙方建立連接,此時可以接收數據
	while(1)
	{
		read(connect_fd,buf,sizeof(buf));
		printf("recv from [%s],data is = %s\n", inet_ntoa(client.sin_addr) ,buf);
		bzero(buf,sizeof(buf));
	}

	return 0;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 先上兩個通用Modbus幫助類,下麵這個是多線程不安全版,在多線程多電機同一埠通信下,可能造成步進電機丟步或者輸出口無響應等,還有個多線程安全版,只是基於這個不安全版加上了LOCK,THIS using Modbus.Device; using Sunny.UI; using System; us ...
  • 最近在項目中,業務上需要與Python進行交互,而Python程式用的配置文件主要是YAML,程式以命令行形式運行,前端頁面由C#通過WPF開發完成。現在需要通過C#生成YAML配置文件,並經過Python讀取和修改後,再次由C#進行讀取。在C#開發程式中,主要用的配置文件主要是XML,JSON,I... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他的軟體在客戶那邊不知道什麼原因崩掉了,從windows事件日誌看崩潰在 clr 里,讓我能否幫忙定位下,dump 也抓到了,既然dump有了,接下來就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼崩潰在 clr 一般來說崩潰在clr ...
  • 問題 對於驗證複雜JSON數據是否合法的需求,通常的解決方式是標準JSON Schema,.Net下有對應的JSON Schema實現庫。應用程式通常需要將標準JSON schema傳入實現庫,來做後續的數據驗證。這裡有一種情況,就是如果使用者不太瞭解標準JSON Schema格式,但又希望能在自己 ...
  • 寫了個盯盤小工具,最近發現很多炒股的小伙伴,上班期間看手機頻繁是不是影響不好?電腦上打開交易軟體,那影響是不是更不好?所以我就寫了個小工具,給大家“摸魚”用。雖然是摸魚用,但是平常丟一邊,或者你自己改造下代碼,寫個死迴圈在控制台裡面刷新等等,或者輸出到VS的輸出欄裡面等等,都行,也不會影響你工作,還 ...
  • 前言:最近幾天有好幾個小伙伴玩WPF,遇到不同頁面,不知道要怎麼傳遞消息。於是,我今天就來演示一個事件聚合器的玩法,採用prism框架來實現。作為福利,內容附帶了主頁面打開對話框時候直接通過參數傳遞消息的一個小例子,具體請自行圍觀。 以下內容,創建wpf項目以及引用prism和實現依賴註入等細節,可 ...
  • 本文分享自天翼雲開發者社區《linux各個目錄的作用》,作者:技術小白 /bin/:存放系統命令的目錄,普通用戶和超級用戶都可以執行,不過放在/bin下的命令在單用戶模式下也可以執行; /sbin/:保存和系統環境設置相關的命令,只有超級用戶可以使用這些命令進行系統環境設置,但是有些命令可以允許普通 ...
  • 目錄傳輸控制協議(TCP)TCP協議 的特點TCP協議的可靠性TCP的連接機制 傳輸控制協議(TCP) 傳輸控制協議(TCP)用於作為包交換電腦通信網路中的主機以及此類網路的互連繫統中的高度可靠的主機對主機協議。 TCP協議 的特點 TCP協議是面向連接的,端到端可靠的協議,該協議被設計適應支持多 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...