Unity_通讯案例_TCP
来源:互联网 发布:网络封包助手 编辑:程序博客网 时间:2024/06/03 17:38
TCP 提供面向连接的服务。TCP 不提供广播或多播服务。由于 TCP 要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销。这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。
网络上两个程序通过双向通信实现数据交换,socket又叫套接字,每个应用程序开启后,都会在传输层端口上绑定一个socket,不同应用程序之间通过寻找端口找到socket实现数据通信。
Socket连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
建立连接
TCP协议提供可靠的面向连接服务,采用三次握手建立连接。
第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到SYN包,向客户端返回ACK(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RCVD状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,也就是ESTABLISHED状态。
终止连接
采用四次挥手断开双向连接。
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端。
(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。
using System;using System.Net;using System.Net.Sockets;using System.Threading;using System.Text;using System.Collections.Generic;namespace TCP{ class Program { static void Main(string[] args) { Server server = new Server(); server.SterUp(); //服务器信息发送 补充; while (true) { string str = Console.ReadLine(); server.SendAll(str); } } } public class Server { //配置相关; private string _ip = "192.168.30.18"; //1024,65535 端口范围; private int _port = 10000; //服务器套接字; private Socket _server; //接受客户端连接的线程,因为Accept是一个阻赛线程的方法,而且此方法还需要循环执行; // accept Client Connect Thread 接受 客户端 连接 线程 private Thread _acceptClientConnectThread; //所有已经连接的客户端; private List<Socket> _clientList =new List<Socket>(); /// <summary> /// 启动服务器=建立流式套接字+配置本地地址; /// </summary> public void SterUp() { try { //固定格式 寻址方案 套接字类型 协议类型 _server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //配置本地地址中 向量转换; EndPoint endPoint = new IPEndPoint(IPAddress.Parse(_ip), _port); //配置本地地址; _server.Bind(endPoint); //监听和接受客户端请求的数量; _server.Listen(30); ////接受客户端连接 运行时需要防火墙许可; //_server.Accept(); //单线程无法继续进行,引入多线程; //Console.WriteLine("执行到这里"); _acceptClientConnectThread = new Thread(AcceptClientConnect); _acceptClientConnectThread.Start(); ////服务器的前四步检测; //Console.WriteLine("{0}:{1} StateUp...",_ip,_port); ////服务器的前四步检测; } catch (Exception e) { Console.WriteLine( e.Message); } } /// <summary> /// Accept Client Connect接受 客户端 连接; /// </summary> public void AcceptClientConnect() { while (true) { try { //接受客户端连接,接一次执行一次, 返回值为客户端的套接字; Socket clientSocket = _server.Accept(); //维护一个客户端列表; _clientList.Add(clientSocket); //获取客户端的网络地址标识 向上转型 ; IPEndPoint clientEndPoint = clientSocket.RemoteEndPoint as IPEndPoint; // 输出 地址 端口 Console.WriteLine("{0}:{1} Connent....", clientEndPoint.Address.ToString(), clientEndPoint.Port); //服务器的前四步检测; //接受客户端消息的线程; Thread acceptClientMsg = new Thread(AcceptMsg); acceptClientMsg.Start(clientSocket); } catch (Exception e) { Console.WriteLine(e.Message); } } } /// <summary> /// 接收消息; /// </summary> public void AcceptMsg(object obj) { // 强转为Socket类型 向下转型; Socket client = obj as Socket; //字节数组 接受传来消息(Receive) 默认的储存缓冲区的大小 64K的大小 1024位1K 等于65534=1024*64 (ReceiveBufferSize); byte[] buffer = new byte[client.ReceiveBufferSize]; //获取客户端的网络地址标识 向上转型 ; IPEndPoint clientEndPoint = client.RemoteEndPoint as IPEndPoint; try { //循环接收消息; while (true) { //接收消息(的长度); int len = client.Receive(buffer); //字符串与字符数组相互转换using System.Text; string str = Encoding.UTF8.GetString(buffer, 0, len); //输出 地址 端口 消息 Console.WriteLine("Receive {0}:{1}:{2}", clientEndPoint.Address.ToString(), _port, str); } } //套接字异常 catch (SocketException e) { Console.WriteLine(e.Message); _clientList.Remove(client); } } /// <summary> /// 发送给某一人; /// </summary> /// <param name="str"></param> /// <param name="client"></param> public void Send(string str ,Socket client) { try { //string=>byte[] byte[] strBytes = Encoding.UTF8.GetBytes(str); client.Send(strBytes); } catch (Exception e) { Console.WriteLine(e.Message); } } /// <summary> /// 发送给所有人信息 添加命名空间和字典 using System.Collections.Generic; /// </summary> public void SendAll(string str) { for (int i = 0; i < _clientList.Count; i++) { Send(str,_clientList[i]); } } //最后关闭套接字; public void Cloce() { //关闭客户端套接字相关; if (_clientList.Count>0) { for (int i = 0; i < _clientList.Count; i++) { _clientList[i].Close(); } } //列表清除; _clientList.Clear(); //关闭服务器套接字相关; _server.Close(); //监听线程关闭; _acceptClientConnectThread.Abort(); } }}
using System;using System.Net;using System.Net.Sockets;using System.Threading;using System.Text;namespace TCP_Client{ class Program { static void Main(string[] args) { Client client = new Client(); client.StartUp(); //发送+测试; //这是要注意关于网络我们会有很多不可控制的错,所以要进行抓错!; while (true) { string str = Console.ReadLine(); client.Send(str); } } } public class Client { //套接字; private Socket _client; //提取出来; private Thread _acceptServerMsg; public void StartUp() { try { _client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //输对方的IP地址 客户端连接; _client.Connect("192.168.30.18", 10000); //F5测试; //客户端的前四步检测; //补充客户端 接受消息的线程; _acceptServerMsg = new Thread(AcceptServerMsg); _acceptServerMsg.Start(); } catch (Exception e) { Console.WriteLine(e.Message); } } //模仿Server 添加完就是双向输入输出; public void AcceptServerMsg() { byte[] buffer = new byte[1024 * 64]; while (true) { try { int len = _client.Receive(buffer); string str = Encoding.UTF8.GetString(buffer, 0, len); Console.WriteLine("Reveive Msg Form Server:{0}", str); } catch (Exception e) { Console.WriteLine(e.Message); } } } /// <summary> /// 发送消息; /// </summary> /// <param name="str"></param> public void Send(string str) { try { //引入using System.Text; //将字符串转换为数组; byte[] strBytes = Encoding.UTF8.GetBytes(str); _client.Send(strBytes); } catch (Exception e) { Console.WriteLine(e.Message); } } /// <summary> /// 客户端 套接字关闭; /// </summary> public void Close() { //连接关闭; if (_client.Connected) { _client.Close(); } //线程关闭; _acceptServerMsg.Abort(); } }}
- Unity_通讯案例_TCP
- Unity_通讯案例_Udp
- Unity_通讯案例_TCP_怎样导入Unity中
- Unity_宠物跟随案例及解析
- 通讯案例
- Unity_协程
- 底层通讯协议问题排查案例
- 底层通讯协议问题排查案例
- EventBus(三)---Fragment案例通讯应用
- 黑马程序员_TCP
- 黑马程序员_TCP
- 黑马程序员_TCP传输
- JavaSE_网络编程_TCP
- Linux _TCP 浅解
- socket编程_TCP协议
- 09_TCP客户服务端
- 网络编程_TCP协议
- NetWork网络_TCP
- CodeForces 279B
- UWP初学的磕磕绊绊:Release版本下GetProperties()方法不能用?
- Shell展开(Shell Expansions)
- 我的c语言第三课
- linux基本命令(十) 文件压缩和传输
- Unity_通讯案例_TCP
- Pandas 处理 dummy variable
- 【python】Windows下使用pip安装python模块时遇到的问题解决
- 八大排序算法之(三)插入排序 折半插入排序
- 花括号展开(Brace Expansion)
- IO流
- 深度学习基础理论探索(二): cross-entropy损失函数的前世今生
- 如何处理不平衡数据
- 用通俗易懂的大白话讲解Map/Reduce原理