Socket编程详解(二)核心代码讲解

本文对代码的讲解基于上一篇博客

快速链接 

Socket编程详解(一)服务端与客户端的双向对话


小试牛刀1:委托声明的关键字和委托方法使用的方法名是不一样的名称 

  1. 可读性:有时,委托的名称可能描述了它的用途或它在哪里被使用,而方法的名称可能更具体地描述了它的功能。将两者分开可以使代码更具可读性。
  2. 重用性:同一个方法可以被多个不同的委托使用。如果你有一个通用的方法,它可以被多个不同的操作触发,那么将这些操作定义为不同的委托可能是有意义的。
  3. 封装性:委托可以封装方法的调用,使你可以在不改变原始方法的情况下更改其调用方式(例如,添加额外的日志记录或错误处理)。
  4. 事件:在C#中,事件是基于委托的。将事件名称与触发事件的方法名称分开是一种常见的做法,因为事件通常表示某种更高层次的概念(如“数据已更改”或“操作已完成”),而方法可能只是实现这个概念的具体细节。

总的来说,将委托和方法的名称分开并不是必须的,但它可以提供更好的可读性、重用性和封装性。然而,在大多数情况下,重要的是保持它们之间的签名一致,以确保它们可以正确地相互引用和使用。


 小试牛刀2:对Main方法的理解

这段代码是C#中Windows Forms应用程序的入口点,通常在Program.cs文件中找到。我将为你逐步解释这段代码:

  1. static void Main():
    这是C#应用程序的入口点。当你运行一个C#控制台应用程序或Windows Forms应用程序时,Main方法是首先被调用的。

  2. Application.EnableVisualStyles();:

    • 这行代码使Windows Forms控件能够使用XP和后续版本的Windows中的视觉样式。这意味着控件将具有与操作系统主题一致的外观和感觉。
    • 默认情况下,如果你不调用此方法,Windows Forms控件可能会使用较旧的、不太吸引人的样式。
  3. Application.SetCompatibleTextRenderingDefault(false);:

    • 这行代码告诉Windows Forms应用程序使用GDI+进行文本渲染,而不是GDI。GDI+是GDI(图形设备接口)的一个增强版本,它提供了更丰富的图形和文本渲染功能。
    • 设置此属性的值为false通常与EnableVisualStyles一起使用,以确保文本和图形都以最佳方式呈现。
    • 在某些情况下,如果你的应用程序需要兼容旧的Windows版本或特定的文本渲染行为,你可能需要将此值设置为true。但在现代Windows Forms应用程序中,通常将其设置为false
  4. Application.Run(new FrmTCPServer());:

    • 这行代码启动Windows Forms应用程序的消息循环,并显示FrmTCPServer窗体。
    • Application.Run是Windows Forms应用程序的核心。它启动一个消息循环,该循环监听来自操作系统的消息(如鼠标单击或键盘按键),并将这些消息传递给相应的窗体或控件进行处理。
    • 在这里,你创建了一个新的FrmTCPServer窗体实例,并将其传递给Application.Run方法。这意味着当你运行此应用程序时,FrmTCPServer窗体将首先被显示。

简而言之,这段代码设置了Windows Forms应用程序的视觉样式和文本渲染方式,并启动了应用程序,显示FrmTCPServer窗体。


小试牛刀3:对方法的理解       

 private void RecMsg(string str) {

         this.txt_Rcv.AppendText(str+Environment.NewLine);

    } 

在这段代码中,RecMsg 是一个方法(函数),它被设计为接收一个字符串参数 str。该方法的主要功能是将传入的字符串 str 添加到 txt_Rcv 这个控件(很可能是 Windows Forms 中的 TextBox 控件)的文本末尾,并在其后添加一个换行符。

这里的 Environment.NewLine 是一个静态属性,它返回当前环境的换行符字符串。在 Windows 系统上,这通常是 \r\n(回车和换行符的组合),而在 Unix 和 Linux 系统上,它通常是 \n(只有换行符)。

这里是一个简单的解释:

  1. RecMsg 方法被调用时,传入一个字符串 str
  2. 方法内部,使用 this.txt_Rcv.AppendText 将 str 添加到 txt_Rcv 控件的当前文本末尾。
  3. 接着,在 str 的后面添加一个换行符,这是通过 Environment.NewLine 实现的。
  4. 这样,每次调用 RecMsg 方法时,都会在 txt_Rcv 控件中看到新添加的一行文本。

如果 txt_Rcv 是一个 TextBox 控件,并且这个 RecMsg 方法是在 Windows Forms 应用程序的某个窗体中定义的,那么这个方法通常会被用于处理接收到的消息,并将这些消息显示在窗体上的文本框中。例如,在 TCP/IP 聊天应用程序中,服务器或客户端可能会调用这个方法来显示从另一端接收到的消息。


小试牛刀4:对监听核心代码的理解

sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(this.txt_IP.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(this.txt_Port.Text.Trim()));

1.AddressFamily(地址族)

地址族是一个用来表示IP地址类型的枚举。在您提供的代码中,AddressFamily.InterNetwork 表示的是 IPv4 地址族。这意味着您创建的套接字将用于处理 IPv4 类型的网络地址。

  • AddressFamily.InterNetwork: 表示 IPv4 地址族。
  • AddressFamily.InterNetworkV6: 表示 IPv6 地址族。

2.SocketType(套接字类型)

套接字类型定义了套接字的基本通信特性。在您提供的代码中,SocketType.Stream 表示一个流套接字,它通常用于面向连接的通信,如 TCP。流套接字提供了一种可靠的、基于字节流的通信方式。

  • SocketType.Stream: 字节流套接字,通常用于 TCP 通信。
  • SocketType.Dgram: 数据报套接字,通常用于 UDP 通信。
  • 还有其他的套接字类型,如 SocketType.Raw 和 SocketType.Rdm,但它们通常用于更底层的网络编程。

3.ProtocolType(协议类型)

协议类型定义了套接字所使用的具体协议。在您提供的代码中,ProtocolType.Tcp 表示使用 TCP 协议。TCP 是一种面向连接的、可靠的、基于字节流的传输层协议。

  • ProtocolType.Tcp: 传输控制协议(TCP)。
  • ProtocolType.Udp: 用户数据报协议(UDP)。
  • 还有其他协议类型,但 TCP 和 UDP 是最常用的。

4.IPEndPoint

IPEndPoint 是一个表示网络端点的类,它包含了一个 IP 地址和一个端口号。在您提供的代码中,您创建了一个 IPEndPoint 对象,其中 address 是一个 IP 地址(可能是 IPAddress 类型的实例或可以转换为 IPAddress 的字符串),而端口号则是从 txt_Port.Text(可能是一个文本框控件的内容)中解析出来的整数。

综上所述,您提供的代码创建了一个用于 TCP 通信的 IPv4 套接字,并指定了一个网络端点(IP 地址和端口号)。这样,您就可以使用这个套接字来与指定的 IP 地址和端口上的服务器或客户端进行通信了。


小试牛刀5:对绑定端口号代码的理解

        sock.Bind(endpoint);
        Invoke(myRcvMsg, "服务器开启成功!");
        MessageBox.Show("开启服务成功!", "打开服务");

1.端口号绑定 (sock.Bind(endpoint);)

        在套接字编程中,Bind 方法用于将套接字与特定的本地地址(IP 地址和端口号)相关联。这告诉操作系统,当有数据到达该 IP 地址和端口时,应该将数据传递给这个套接字。在您提供的代码中,endpoint 是一个 IPEndPoint 对象,它包含了 IP 地址和端口号。sock.Bind(endpoint); 就是将套接字 sock 绑定到这个 endpoint 上。

2.Invoke 方法

        在 Windows Forms 应用程序中,如果你尝试在不是由控件创建的线程上直接更新控件(例如,在后台线程中更新 UI),那么你会遇到线程安全问题,并可能导致异常。为了避免这种情况,你可以使用控件的 Invoke 方法来在控件的创建线程上执行代码。

        这里 myRcvMsg 应该是一个委托实例,它指向一个方法,该方法接受一个字符串参数(在这里是 "服务器开启成功!")。

3.MessageBox.Show 方法

  MessageBox.Show 方法用于显示一个消息框。它可以有不同的重载版本,接受不同数量的参数。在您提供的代码中,MessageBox.Show("开启服务成功!", "打开服务"); 使用了两个参数:

  • 第一个参数 "开启服务成功!" 是要显示的消息文本。
  • 第二个参数 "打开服务" 是消息框的标题。

      总结起来,您的代码首先绑定套接字到指定的 IP 地址和端口,然后尝试使用 Invoke 方法来更新 UI(尽管这里的具体实现可能不完全正确),最后使用 MessageBox.Show 方法来显示一个消息框。如果您的目的是在 UI 线程上显示消息框,那么通常不需要使用 Invoke 来包装 MessageBox.Show 调用,因为 MessageBox.Show 本身是线程安全的,并且会自动在 UI 线程上执行。

针对这个MessageBox.Show()方法,有个地方会经常用到,就是捕捉异常的时候

        根据下面这个代码理解这个方法:

        这里是一个catch捕捉异常,此处的MessageBox.Show()方法里面的ex.Message会弹出什么内容呢?是不是MessageBox.Show()方法会根据不同的异常弹出不一样的内容吗?catch(Exception ex) { MessageBox.Show("开启服务失败" + ex.Message, "打开服务"); return; }

        在C#中,catch(Exception ex) 语句用于捕获在try块中抛出的任何异常。当异常被捕获时,ex(在这里是一个Exception类型的变量)将包含有关该异常的详细信息。

  ex.Message 属性包含了异常的描述性消息,这个消息通常描述了异常发生的原因这个消息是由抛出异常的代码生成的,可能是一个通用的描述(如“发生了一个未处理的异常”),也可能是一个更具体的描述(如“无法连接到数据库服务器”或“索引超出了数组的范围”)。

       在你的catch块中,MessageBox.Show("开启服务失败" + ex.Message, "打开服务"); 这行代码将会弹出一个消息框,标题为“打开服务”,而消息内容为“开启服务失败”后面跟上ex.Message的内容。

       因此,确实,MessageBox.Show() 方法会根据不同的异常弹出不一样的内容,因为ex.Message的内容会根据抛出的具体异常而变化。

       例如,如果抛出的异常是因为网络问题导致的,ex.Message 可能会是类似于“无法连接到远程服务器”这样的消息。那么,用户将会看到一个消息框,内容是“开启服务失败无法连接到远程服务器”,标题是“打开服务”。

       如果抛出的异常是因为数组越界,ex.Message 则可能会是“索引超出了数组的范围”,那么用户将会看到一个消息框,内容是“开启服务失败索引超出了数组的范围”,标题是“打开服务”。

小试牛刀6:对socket对象.Listen(10)的理解

在网络编程中,特别是使用TCP/IP套接字(Socket)时,sock.Listen(10); 这行代码表示服务器套接字(sock)现在准备好开始监听来自客户端的连接请求,并且它有一个“挂起连接队列”的容量大小为10。

这里是这行代码的详细解释:

  • sock: 这是一个服务器套接字对象,通常是在创建套接字(使用如Socket类的构造函数)并绑定到一个特定的IP地址和端口号后得到的。
  • Listen: 这是Socket类的一个方法,用于将套接字置于监听模式,以便它可以接受来自客户端的连接请求。
  • 10: 这是传递给Listen方法的参数,它指定了挂起连接队列的最大长度。挂起连接队列是一个内部数据结构,用于存储来自客户端的连接请求,当服务器太忙而不能立即接受连接时。队列中的每个条目都代表一个尚未被Accept方法处理的连接请求。

在这个例子中,如果服务器套接字(sock)同时收到超过10个连接请求,并且它还没有通过Accept方法接受任何连接,那么第11个及以后的连接请求将会被丢弃或拒绝,直到队列中有空间为止。

注意:仅仅调用Listen方法并不会使服务器自动接受连接。你需要在一个单独的线程(或使用异步方法)中调用Accept方法,以便在连接请求到达时进行处理。Accept方法将从挂起连接队列中取出一个连接请求,并返回一个新的套接字对象,该对象表示与客户端的已建立连接。然后,你可以使用这个新的套接字对象与客户端进行通信。

  • 17
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值