(一)CSharp-Socket

news/2024/11/16 13:47:06/

一、套接字

请添加图片描述

Windows Sockets 只支持一个通信域:网际域(AF-INET),这个域被使用网际协议族通信的进程所使用。

TCP/IP 的 Socket 则提供3种类型的套接字

1、流式套接字(SOCK_STREAM)
提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传输协议(FTP)即使用流式套接字。

2、数据报式套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立包形式发送,不提供无差错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。

3、原始套接字(SOCK_RAW)
该接口允许对较低层协议,如 IP、ICMP 直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。

二、C/S 编程模式

通信的两个进程间相互作用的主要模式式客户机/服务器模式。
客户端: 请求另一台计算机上的服务(如访问数据库)的计算机。
服务端: 处理这些服务请求(例如对数据库进行检索,将结果返回)的计算机。

对称协议: 每一方都有可能扮演主从角色。
非对称协议: 一方被不可改变的认为是主机,而另一方则是从机。

三、Socket 编程的通信方式

1)同步方法
通信的同步,指客户端在发送请求后,必须在服务端有回应后才能发送下一个请求。所以这个时候的所有请求将会在服务端得到同步。

(2)异步方法
通信的异步,指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求,这样对于所有的请求动作来说将会在服务端得到异步,这条请求的链路就像是一个请求队列,所有的动作在这里不会得到同步。

3)阻塞方式
阻塞套接字是指执行此套接字的网络调用时,所调用的函数只有在得到结果之后才会返回,在调用结果返回之前,当前线程会被挂起,即此套接字一直阻塞在网络调用上。比如调用 StreamReader 类的 ReadLine() 方法读取网络缓冲区的数据,如果调用的时候没有数据到达,那么此 ReadLine() 方法将一直挂在调用上,直到读到一些数据,此函数才返回。

(4)非阻塞方法
非阻塞套接字是指在执行此套接字的网络调用时,即使不能立刻得到结果,该函数也不会阻塞当前线程,而会立刻返回。对于非阻塞套接字,同样调用 StreamReader 类的 ReadLine() 方法读取网络缓冲区的数据,不管是否读取数据都立即返回,而不会一直挂在此函数调用上。

阻塞对象上可以有非阻塞的调用方式,可以通过一定的 API 去轮询状态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。

客户端/服务端结构的软件采用的方式就是异步非阻塞模式。在利用 C# 进行网络编程时,由于 .NET Framework SDK 对阻塞和非阻塞的工作机制进行了封装。

四、.NET 中的 Socket 类

1、Socket 类

1)TCP Socket:

请添加图片描述

2)UDP Socket:

请添加图片描述

Socket 类的构造函数原型:

public Socket(
AddressFamily addressFamily,//对于常规 IP 通信网络,只能使用 AddressFamily.InterNetwork。
SoncketType socketType,
ProtocolType protocolType
);

AddressFamily: 用来指定网络类型;
SoncketType: 用来指定套接字类型(即数据连接方法)
ProtocolType: 用来指定网络协议。

表- IP 套接字定义组合

SocketType 值ProtocolType 值描述
StreamTcp面向连接套接字
DgramUdp无连接套接字
RawIcmp网际消息控制协议套接字
RawRaw基础传输协议套接字

表- Socket 类的公共属性

属性名描述
AddressFaimly获取 Socket 的地址族
Available获取已经从网络接收且可供读取的数据量
Blocking获取或设置一个值,该值指示 Socket 是否处于阻塞模式
Connected获取一个值,该值指示 Socket 是否已连接到远程主机
Handle获取 Socket 的操作系统句柄
LocalEndPoint获取本地终结点 EndPoint
RemoteEndPoint获取远程终结点 EndPoint
ProtocolType获取 Socket 的协议类型
SocketType获取 Socket 的类型

2、Socket 类的常用方法

(1)Bind(EndPoint adddress)
在服务器端,当一个套接字被创建后,需要将它绑定到系统的一个特定地址。可以使用 Bind() 方法来完成,其参数为一个 IPEndPoint 实例(包含 IP 地址和端口信息)。

(2)Listen(int con_num)
服务器端的套接字完成了与地址的绑定后,就使用 Listen() 方法监听客户发送的连接请求。其参数 con_num 为一整型值,该值表示服务器可以接收的最大连接数目。超过这个数目的连接都会被拒绝。con_num 数值的设定会影响到服务器的运行,因为每个接受的连接都要使用 TCP 缓冲区,如果连接的数目过大,收发数据的缓存将减少。

(3)Accept()
在服务器进入监听状态时,如有从客户端发来的连接请求,服务器将使用 Accept() 方法来接受连接请求。 Accept() 返回一个新的套接字,该套接字包含所建立的连接的信息并负责处理本连接的所有通信。而服务器刚开始创建的套接字仍然负责监听,并在需要时调用 Accept() 接受新的连接请求。

(4)Send()
当服务器接受了来自客户端的连接请求后,服务器和客户端双方就可以利用 Send() 方法来发送数据。

表-Send()、Receive() 重载方法

方法说明
Send(byte[] data)将数据发送到连接的 Socket
Send(byte[] data, SocketFlags sf)使用指定的 SocketFlags 将数据发送到连接的 Socket
Send(byte[] data , int size, SocketFlags sf)使用指定的 SocketFlags,将指定字节数的数据发送到已连接的 Socket
Send(byte[] data, int offset, int size, SocketFlags sf)使用指定的 SocketFlags,将指定字节数的数据发送到已连接的 Socket(从指定的偏移量开始)
Receive(byte[] data)从绑定的套接字接收数据,将数据存入接收缓冲区
Receive(byte[] data, SocketFlags sf)使用指定的 SocketFlags,从绑定的套接字接收数据,将数据存入接收缓冲区
Receive(byte[] data, int size, SocketFlags sf)使用指定的 SocketFlags,从绑定的套接字接收指定字节数的数据,并将数据存入接收缓冲区
Receive(byte[] data , int pffset, int size, SocketFlags sf)使用指定的 SocketFlags,从绑定的套接字接收指定字节数的数据,并将数据存入接收缓冲区的指定偏移量位置

(5)Receive()
当服务器接受了来自客户端的连接请求后,服务器和客户端双方就可以利用 Receive() 方法来接受数据。

(6) Connect(EndPoint remoteEP)
同服务器端一样,客户端的套接字建立后也必须与一个地址绑定。在客户端使用 Connect() 方法实现绑定,remoteEP 参数为索要连接的服务器端的 IPEndPoint 实例。调用 Connect() 方法后,它将一直阻塞到连接建立,如果连接不成功,将返回一个异常。

(7)Shutdown(SocketShutdown how)
当客户端和服务器端的通信结束时,必须关闭相应的套接字实例。可以使用 Shutdown() 方法来禁止该套接字上的发送和接收,Shutdown() 方法有一个枚举类型的参数,如 SocketShutdown.Send 表示禁用发送套接字,SocketShutdown.Receive 表示禁用接收套接字,SocketShutdown.Both 表示禁用发送和接收的套接字。

(8)Close()
禁止套接字上的发送和接收之后,使用 Close() 方法关闭套接字连接并释放所有相关资源。这样套接字会在系统内部缓冲区处理完毕后套接字并释放资源。

代码例子

        static void Main(string[] args){//创建 IPEndPoint 实例IPAddress ipa = IPAddress.Parse("127.0.0.1");IPEndPoint ipep = new IPEndPoint(ipa, 8080);//创建 Socket 实例Socket test_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);Console.WriteLine("AddressFamily:{0}", test_socket.AddressFamily);Console.WriteLine("SocketType:{0}", test_socket.SocketType);Console.WriteLine("ProtocolType:{0}", test_socket.ProtocolType);Console.WriteLine("Blocking:{0}", test_socket.Blocking);//修改 Socket 实例的属性test_socket.Blocking = false;Console.WriteLine("new Blocking:{0}", test_socket.Blocking);Console.WriteLine("Connected:{0}", test_socket.Connected);//调用 Bind() 方法,使 Socket 与一个本地终结点相关联test_socket.Bind(ipep);IPEndPoint sock_iep = (IPEndPoint)test_socket.LocalEndPoint;Console.WriteLine("Local EndPoint:{0}", sock_iep.ToString());//关闭 Sockettest_socket.Close();Console.ReadKey();}

输出结果:

AddressFamily:InterNetwork
SocketType:Stream
ProtocolType:Tcp
Blocking:True
new Blocking:False
Connected:False
Local EndPoint:127.0.0.1:8080

http://www.ppmy.cn/news/583609.html

相关文章

基于 Redis 手写一个“秒杀”

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌ Java知识图谱点击链接:体系化学习Java(Java面试专题) 💕💕 感兴趣的同学可以收…

C4.5算法

假设我们有一个关于餐厅顾客的数据集,其中包括9个样本,每个样本有3个属性:天气、是否有预订和是否是周末,以及一个类别标签,表示该顾客是否会来餐厅(是或否)。 数据集如下: 使用C4.5算法来构建…

你知道ai绘画生成器怎么弄吗

在数字时代,艺术也开始走向了自动化。随着人工智能技术的进步,ai绘画软件已经开始逐渐普及。它们可以利用先进的神经网络算法,学习人类艺术家的风格和技巧,从而生成出高度逼真的艺术作品。这些作品虽然没有人类艺术家的创意和灵魂…

centos7上部署haproxy+nginx+nfs

服务器 文章目录 服务器一、背景二、硬件与环境需求1、关闭所有服务器防火墙4、部署nginx服务器2 5 测试 一、背景 两台nginx服务器做web服务,haproxy服务器做调度负载均衡,为保证提供的内容一致性使用nfs做共享目录,两台nginx服务器使用相同…

历史类:罗马帝国兴亡史

历史类:罗马帝国兴亡史 罗马王国罗马王政时代 罗马共和国执政官和元老院保民官迦太基布匿战争 凯撒屋大维 罗马帝国二帝共治四帝共治君士坦丁大帝狄奥多西东/西罗马帝国西罗马帝国神圣罗马帝国 东罗马帝国 奥斯曼帝国 罗马王国 公元前753年到前509年 还记得特洛伊…

罗马帝国简史

最早的罗马是由一些村落合并而成的。村落散布的地带离海岸不远,土壤肥沃,适于农业和畜牧业的发展。公元前1000年左右已有一些部落就出现在这里,到了公元前800-700年时,一个称作“七丘同盟”的联合组织出现了,后来又有些…

「罗马人的故事 III 胜者的迷思」读后感 Part1,格拉古兄弟

「罗马人的故事 III 胜者的迷思」读后感 Part1,格拉古兄弟 第二本 罗马人的故事 II 汉尼拔战记 描述了了罗马公敌——汉尼拔巴卡 的前世今生,自然而然的,第三本罗马人的故事的时间线推进到了汉尼拔死后的罗马,时间跨度从 147 BC&…

罗马字符及数字

罗马字符及数字 小写 大写 中文 英文 α Α 阿尔法 aerfar β Β 卑塔 beita γ Γ 嘎吗 gama δ Δ 德儿塔 derlta ε Ε 依普西龙 ipuseilong ζ Ζ zei塔 zeita η Η 衣塔 …