C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨

C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨

简介

本文主要介绍使用C#进行Socket网络编程时,涉及到的TCP/IP协议中的各个层次模型、端口以及报文等内容,并提供两个基本示例进行说明。

TCP/IP协议层次模型

TCP/IP协议是网络通信的基础,它将网络通信分为许多层,每一层负责不同的任务。这些层从下往上分别是:物理层、数据链路层、网络层、传输层、应用层。

下面是这些层级及其任务的简单描述:

  • 物理层:定义网络的物理布局以及底层数据传输,如电流、电压等。

  • 数据链路层:负责在物理层上,根据MAC地址,完成节点之间的通信;将从网络层接收到的IP数据报组成帧,在物理层上传输。

  • 网络层:为数据通信提供路由、寻址、分包等服务,负责网间的数据传输,通过IP地址来唯一标识不同的设备。

  • 传输层:为上层协议提供可靠的端到端通信,并提供差错检测和重传等机制,常用的协议有TCP和UDP。

  • 应用层:我们编写的程序所用的协议,如HTTP、FTP、SMTP等。

Socket端口

在TCP/IP协议中,每个设备都有一个IP地址,但这个地址只是标识了设备,而没有标识一个应用程序。为了实现设备与设备之间的通信,需要一个能够分辨应用程序的标识,这个标识就是端口。

端口是一个16位的整数,范围从0到65535,其中0到1023是被保留的,一般作为著名的端口使用,如HTTP协议的80端口、FTP协议的21端口等;1024到65535是动态端口,由操作系统分配给应用程序使用。

Socket报文

Socket报文是进行网络通信时所传输的数据单元,可以理解为一段二进制数据流。在TCP/IP协议中,Socket报文主要有三部分组成:

  • IP头部:包含了发送方和接收方的IP地址,IP协议版本,以及一些与IP协议相关的控制字段。

  • TCP头部:包含了TCP协议的各种控制字段,如端口号、序列号和确认号等。

  • 数据段:将应用程序的数据流发送给TCP层,并分段传输。

示例一:Socket服务端及其客户端

下面是一个简单的Socket服务端和客户端程序实例,适用于 TCP/IP 协议:

  1. 服务端:
using System;  
using System.Net;  
using System.Net.Sockets;  
using System.Text;

class Program  
{  
    static void Main(string[] args)  
    {  
      try  
      {  
            IPAddress ipAd = IPAddress.Parse("127.0.0.1");  
            TcpListener myList=new TcpListener(ipAd, 8001);  

            myList.Start();  
            Console.WriteLine("等待客户端连接......");  

            while(true)  
            {  
                TcpClient client = myList.AcceptTcpClient();  
                Console.WriteLine("客户端已连接...");  

                NetworkStream netStream = client.GetStream();  
                byte[] bytes = new byte[1024];  
                int i = netStream.Read(bytes, 0, bytes.Length);  
                string data = Encoding.ASCII.GetString(bytes, 0, i);  
                Console.WriteLine("收到客户端消息: {0}", data);  

                string response = "谢谢连接我们,再见!";  
                byte[] message = Encoding.ASCII.GetBytes(response);  
                netStream.Write(message, 0, message.Length);  
                client.Close();  
            }  
            myList.Stop();  
        }  
        catch (Exception e)  
        {  
            Console.WriteLine("出现异常: {0}", e.ToString());  
        }  
   }
}  
  1. 客户端:
using System;  
using System.Net;  
using System.Net.Sockets;  
using System.Text;  

class Program  
{  
    static void Main(string[] args)  
    {  
        try  
        {  
            TcpClient tcpclnt = new TcpClient();  
            Console.WriteLine("向服务端发送连接请求......");  
            tcpclnt.Connect("127.0.0.1", 8001);  

            byte[] bytes = Encoding.ASCII.GetBytes("客户端发送的数据......");  
            NetworkStream stream = tcpclnt.GetStream();  
            stream.Write(bytes, 0, bytes.Length);  
            Console.WriteLine("向服务端发送消息: {0}", Encoding.ASCII.GetString(bytes, 0, bytes.Length));  

            bytes = new byte[1024];  
            int i = stream.Read(bytes, 0, bytes.Length);  
            Console.WriteLine("从服务端收到消息: {0}", Encoding.ASCII.GetString(bytes, 0, i));  

            tcpclnt.Close();  
        }  
        catch (Exception e)  
        {  
            Console.WriteLine("出现异常: {0}", e.ToString());  
        }  
    }  
}  

示例二:Socket异步通信

下面的示例演示一个异步的Socket服务器,它可以同时处理多个请求。

using System;  
using System.Net;  
using System.Net.Sockets;  
using System.Text;

class Program  
{  
    static int port = 8001;  
    static TcpListener listener = new TcpListener(IPAddress.Any, port);  

    static void Main(string[] args)  
    {  
        listener.Start();  
        Console.WriteLine("等待客户端连接...");

        var state = new StateObject();  

        while(true)  
        {  
            listener.BeginAcceptTcpClient(AcceptTcpClientCallback, state);  
            Console.WriteLine("正在等待下一个客户端连接...");  
        }  
    }  

    static void AcceptTcpClientCallback(IAsyncResult ar)  
    {  
        Console.WriteLine("客户端连接成功...");  

        var state = (StateObject)ar.AsyncState;  
        TcpClient client = listener.EndAcceptTcpClient(ar);   
        state.Client = client;  

        NetworkStream stream = state.Client.GetStream();  
        byte[] buffer = new byte[1024];  
        stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, state);  
    }  

    static void ReadCallback(IAsyncResult ar)  
    {    
        var state = (StateObject)ar.AsyncState;  
        NetworkStream stream = state.Client.GetStream();  
        int length = stream.EndRead(ar);  

        string data = Encoding.ASCII.GetString(state.Buffer, 0, length);  
        Console.WriteLine("收到客户端消息:{0}", data);  

        byte[] responseBytes = Encoding.ASCII.GetBytes("谢谢友善的客户端!");  
        stream.BeginWrite(responseBytes, 0, responseBytes.Length, WriteCallback, state);  
    }

    static void WriteCallback(IAsyncResult ar)  
    {  
        var state = (StateObject)ar.AsyncState;  
        NetworkStream stream = state.Client.GetStream();  
        stream.EndWrite(ar);  
        stream.BeginRead(state.Buffer, 0, state.Buffer.Length, ReadCallback, state);  
    }
}  

class StateObject  
{  
    public TcpClient Client { get; set; }  

    public byte[] Buffer = new byte[1024];  
}  

上面的代码中,异步通信主要通过BeginXXX和EndXXX方法进行,回调函数则负责对数据进行处理和响应数据。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C#预定义数据类型之值类型和引用类型介绍

    C#预定义数据类型之值类型和引用类型介绍 一、值类型和引用类型的区别 在C#中,数据类型可以分为值类型和引用类型两种。 值类型表示的是实际的值,它们被存储在堆栈中。当在一个方法中传递值类型之间的参数时,它们会被复制一份,因此赋予新值时不会影响原始的值。 值类型的数据包括: 布尔型(bool); 数字类型: 整型(byte、sbyte、short、ushort…

    C# 2023年5月31日
    00
  • Unity为软件添加使用有效期的具体步骤

    为软件添加使用有效期是保护软件版权、防止盗版的一种常用手段之一。下面是Unity为软件添加使用有效期的具体步骤: 创建一个有效期脚本 首先,你需要创建一个有效期脚本,用来判断软件是否过期。在Unity中可以使用C#编写该脚本,通常需要作以下几个步骤: 创建脚本文件。在Unity的Project面板中,右键点击Assets文件夹,在弹出的菜单中选择Create…

    C# 2023年6月1日
    00
  • 枚举的用法详细总结

    枚举的用法详细总结 枚举(Enumeration)是一种常用的数据类型,它可以定义一些有限的取值范围。枚举常用于程序中对一些离散的状态或类型的定义,也方便了程序的维护和理解。在本文中,我们将介绍枚举的定义、初始化、遍历以及一些常见的用法。 定义枚举 定义枚举可以使用C++11引入的关键字enum class,其语法如下: enum class 枚举名 { 枚…

    C# 2023年6月8日
    00
  • 在Winform程序中使用Spire.Pdf实现页面添加印章功能的实现

    实现在Winform程序中添加印章功能可以使用Spire.Pdf组件,具体实现步骤如下: 步骤一:添加Spire.Pdf组件 要使用Spire.Pdf组件,首先需要将该组件添加到Winform项目中。具体方法如下: 在Visual Studio中打开Winform项目。 在Solution Explorer中选择该项目。 在右侧Properties窗口中选择…

    C# 2023年6月7日
    00
  • c#.NET 写txt文件小例子

    下面是详细的攻略: 1. 准备工作 在开始编写代码之前,需要准备好以下工具和环境: 电脑上已安装 .NET Framework。 某个文本编辑器或 IDE,比如 Visual Studio。 一些基本的 C# 编程知识。 2. 创建 C# 项目 创建一个新的 C# 项目: 打开 Visual Studio,选择 “新建项目”。 在弹出的 “新建项目” 窗口中…

    C# 2023年5月31日
    00
  • C#使用dir命令实现文件搜索功能示例

    下面是C#使用dir命令实现文件搜索功能示例的详细攻略: 1.使用Process类调用cmd命令 在C#中,可以使用Process类调用外部程序,通过cmd命令来实现搜索文件的功能。具体过程如下: //定义Process进程调用cmd Process p = new Process(); p.StartInfo.FileName = "cmd.ex…

    C# 2023年6月1日
    00
  • 学习TraceLogging事件,使用ETW记录,并使用WPA捕获和分析跟踪

    优化响应行为的交互 下载WINDOWS评估和部署工具包 (Windows ADK) 保持默认安装 驱动延迟优化的基本步骤包括: 定义方案并添加 TraceLogging 事件。TraceLogging 是用于日志记录事件的系统,无需清单即可解码,TraceLogging基于windows事件跟踪(ETW),并提供检测代码的简化办法。C#可选的有.NET Ev…

    C# 2023年4月30日
    00
  • C#微信公众平台开发之access_token的获取存储与更新

    C#微信公众平台开发之access_token的获取存储与更新 前言 微信公众平台开发中,access_token是关键的全局唯一接口调用凭据,获取access_token是进行后续接口调用的必要步骤。因为获取access_token每日调用次数有限,并且获取access_token的过程中存在一些约束和具体的有效期,所以需要进行存储和更新。 本文将详细介绍…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部