一、Socket: Socket包括Ip地址和端口号两部分,程序通过Socket来通信,Socket相当于操作系统的一个组件。Socket作为进程之间通信机制,通常也称作”套接字”,用于描述IP地址和端口号,是一个通信链的句柄。说白了,就是两个程序通信用的。(Socket不仅可以在两台电脑之间通信,还可以在同一台电脑上的两个程序间通信。)
二、创建Socket:Scoket类的构建方法有多个重载其中最常用的重载接受三个参数:
参数 | 说明 |
---|---|
addressFamily | 第一个参数是一个AddressFamily枚举变量,这个参数指定了这个Scoket对象所使用的IP地址族(IP 版本 4 地址、IP 版本 6 的地址 等) |
socketType | 第二参数是一个SocketType枚举值,其指定了这个Scoket对象用来传递的数据类型 |
ProtocolType | 第三个参数是一个ProtocolType枚举值,其指定了这个Scoket对象使用的协议 |
三、TCP协议通信的基本步骤:
服务器端:
第一步:创建一个用于监听连接的Socket对像;
第二步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第三步:用socket对像的Bind()方法绑定EndPoint;
第四步:用socket对像的Listen()方法开始监听;
第五步:接收到客户端的连接,用socket对像的Accept()方法创建一个新的用于和客户端进行通信的socket对像;
第六步:通信结束后一定记得关闭socket;
客户端:
第一步:建立一个Socket对像;
第二步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第三步:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求;
第四步:如果连接成功,就用socket对像的Send()方法向服务器发送信息;
第五步:用socket对像的Receive()方法接受服务器发来的信息 ;
第六步:通信结束后一定记得关闭socket;
四、Socket的基本方法:
方法 | 说明 |
---|---|
Bind(EndPoint localEP) | 向操作系统申请一个可用的ip和端口号用来做通信 |
Listen(int backlog) | 监听连接的客户端,其接受一个int类型的参数用来指定挂起的连接队列的最大长度 |
Accept() | 暂停当前线程,直到有一个客户端连接过来,之后进行下面的代码,其返回一个Socket对象,可以使用这个对象和客户端做通信 |
Send(byte[] buffer) | 将数据发送到相对应的客户端Socket上。参数为一个byte数组 |
Receive(byte[] buffer) | 从绑定接收数据Socket 到接收缓冲区中。Byte 类型的数组 ,它是接收到的数据的存储位置。返回收到的数据的字节数 |
Connect(EndPoint remoteEP) | 通过 IP加上端口定位一个要连接的服务端 |
Close(int timeout) | 关闭 Socket 连接并释放所有与指定超时关联的资源,以允许要发送的数据排队。等待最多 timeout 秒钟后,即可发送任何剩余数据,然后关闭套接字 |
Shutdown(SocketShutdown how) | 禁用发送和接收的 Socket,参数用来指定禁用接收还是发送,或者两个都禁用 |
Poll(int microSeconds, SelectMode mode) | 确定Socket的状态 ,第一个参数为等待的时间(以微秒为单位)。第二个参数是SelectMode枚举值指定要确定的状态 |
ReceiveFrom(byte[] buffer, ref EndPoint remoteEP); | 用与UDP协议接收消息,其返回消息来源的ip和端口号 |
1、端口:在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应用程序),因此,在网络协议中使用端口号识别主机上不同的进程。
2.IP地址:用来在网络中标记一台电脑的一串数字,C#用IPAddress对象来存储IP地址。
五、UDP 协议通信:(不需要建立连接的过程)
1、Socket:UDP的socket的参数与tcp不同,如下所示:
//使用数据报发送消息,使用UDP协议
Socket udpServer = new Socket
(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
2、接收数据的方法:
//这个方法会把数据来源(ip+port)放进第二个参数
int length= udpServer.ReceiveFrom(data,ref remoteEndPoint);
六、TCP示例:
//tcp客户端
//1.创建socket
Socket tcpClient = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.发起建立的连接请求
IPAddress iPAddress = IPAddress.Parse("172.16.3.4");
EndPoint point = new IPEndPoint(iPAddress, 7788);
tcpClient.Connect(point);//通过 IP加上端口定位一个要连接的服务端
byte[] data = new byte[1024];
//byte数组data用来接受数据
//返回值length表示接受了多少字节的数据
int length = tcpClient.Receive(data);
string message= Encoding.UTF8.GetString(data,0,length)
Console.WriteLine(message);
//向服务器端发送消息
string message2 = Console.ReadLine();
tcpClient.Send(Encoding.UTF8.GetBytes(message2));
//TCP服务端
//1.创建socket
Socket tcpServer = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.绑定ip跟端口号 192.16.3.4
IPAddress iPAddress = new IPAddress(new byte[] { 172,16,3,4 });
EndPoint point = new IPEndPoint(iPAddress ,7788);//ipEndPoint时对ip+端口号做了一层封装
tcpServer.Bind(point);//向操作系统申请一个可用的ip和端口号用来做通信
//3开始监听(等待客户端连接)
tcpServer.Listen(100);
Console.WriteLine("开始监听客户端");
//暂停当前线程,直到有一个客户端连接过来,之后进行下面的代码
//使用返回的socket跟客户端做通信
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("一个客户端连接过来了");
string message = "hello 欢迎你";
byte[] date= Encoding.UTF8.GetBytes(message);//对字符串进行编码,的到一个字符串的字节数组
clientSocket.Send(date);
Console.WriteLine("向客户端发送了一条数据");
//创建一个字节数组去承接客户端发送过来的数据
byte[] data2 = new byte[1024];
int length = clientSocket.Receive(data2);
string message2 = Encoding.UTF8.GetString(data2, 0, length);
Console.WriteLine("接受到了一条消息"+message2);
Console.ReadKey();
七、UDP示例:
//服务端UDP
Socket udpServer = new Socket
(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpServer.Bind(new IPEndPoint(IPAddress.Parse("172.16.3.4"), 7788));
//接收数据
byte[] data = new byte[1024];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
//这个方法会把数据来源(ip+port)放进第二个参数
//这个方法会暂停当前线程
int length= udpServer.ReceiveFrom(data,ref remoteEndPoint);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("从ip:" + (remoteEndPoint as IPEndPoint).Address.ToString() +
":" + (remoteEndPoint as IPEndPoint).Port.ToString()+"发来"+message);
udpServer.Close();
Console.ReadKey();
//UDP客户端
//创建socket
Socket udpClient = new Socket
(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//发送消息
EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("172.16.3.4"), 7788);
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, serverPoint);
Console.ReadKey();
八、TcpListener
1.TcpListener类t对socket类做了简单的封装。TcpListener可以直接使用ip地址和端口号来创建TcpListener实例。使用Start()方法开始监听客户端,调用AcceptTcpClient()方法等待客户端连接,这个方法返回一个TcpClient实例。使用这个TcpClient实例能搞读取客户端中传递过来的信息。
2.服务器端通信基本步骤
- 新建TcpListener实例:TcpListener listener = new TcpListener(IPAddress.Parse("172.16.3.4"), 7788);
- 调用Start()方法开始监听:listener.Start();
- 调用AcceptTcpClient()方法等待客户端连接:TcpClient client = listener.AcceptTcpClient();
- 使用返回的TcpClient 实例读取客户端传来的方法:NetworkStream stream= client.GetStream();
- 使用返回的NetworkStream读取网络流中的信息:int length = stream.Read(data, 0, 1024);
- 最后转换消息的类型输出。
3、TcpListener常用方法
方法 | 说明 |
---|---|
TcpListener(IPAddress localaddr, int port) | 新实例初始化TcpListener 类用于侦听传入的连接尝试在指定的本地 IP 地址和端口号。 |
Start() | 开始侦听传入的连接请求。 |
AcceptTcpClient() | 接受挂起的连接请求。 返回结果:一个TcpClient 用来发送和接收数据。 |
Start() | 关闭侦听程序。 |
九、TcpClient
1、TcpClient类对socket类做了简单的封装。TcpClient 可以直接使用ip地址和端口号来创建TcpClient 实例。使用网络流进行数据通信
2、客户端通信基本步骤
- 新建TcpClient实例,它会自动连接相应的计算机:TcpClient client = new TcpClient("172.16.3.4", 7788);
- 通过网络流进行数据交换:NetworkStream stream = client.GetStream();
- 往网络流中写入消息:stream.Write(data, 0, data.Length);