網路編程練習題---利用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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...