TCP实现一个简易的聊天室 (Unity&&C#完成)
效果展示
tcp
transmission control protocol 传输控制协议
tcp是面向连接的流模式(俗称:网络流)。即传输数据之前源端和终端建立可靠的连接,保证数据传输的正确性。
流模式:由于建立连接,收到的数据都是同一主机发送的,所有可以发送端write一次,接收端read多次;也可以发送端write多次,接收端read多次。但每次传输数据最大为1460字节。
实现步骤
服务端 客户端
获取本机终结点 获取服务器终结点
创建tcplistener对象,开启侦听器 创建tcpclient对象
等待客户端连接 连接服务器
获取针对客户端连接的网络流客户端通信 通过网络流与服务器通信
…… ……
关闭连接 关闭连接
using system.collections; using system.collections.generic; using system.net.sockets; using unityengine; using common; using unityengine.ui; using system.net; using system; using system.text; /// <summary> /// tcp 客户端 发送消息 /// </summary> public class chattcpclienttest : monobehaviour { private inputfield messageinput; private tcpclient tcpclient; private void start() { var server = findobjectoftype<chattcpservertest>(); ipendpoint ep = new ipendpoint(ipaddress.parse(server.serverip), server.serverport); //创建终结点 tcpclient = new tcpclient(); //1. 创建socket tcpclient.connect(ep); ////三次握手(连接请求) //使用指定的远程网络终结点将客户端连接到tcp主机 messageinput = transform.findchildbyname("messageinput").getcomponent<inputfield>(); transform.findchildbyname("send").getcomponent<button>().onclick.addlistener(onsendbuttonclient); } private void onsendbuttonclient() { sendchatmessage(messageinput.text); } private void sendchatmessage(string msg) { //获取网络流 networkstream stream = tcpclient.getstream(); //用于发送消息和接收消息 byte[] dgramcontent = encoding.utf8.getbytes(msg); //传入内容 stream.write(dgramcontent, 0, dgramcontent.length); //写入网络流 内容 从那开始发 发的长度 } /// <summary> /// 3.关闭连接/释放资源 /// </summary> private void onapplicationquit() { tcpclient.close(); } }
using system.collections; using system.collections.generic; using system.net; using system.net.sockets; using system.text; using system.threading; using uiwidgetssamples; using unityengine; using common; using system; /// <summary> /// 服务端 tcp 接收消息 /// </summary> public class chattcpservertest : monobehaviour { public string serverip; //ip public int serverport; //端口 //1.创建socket对象 private chatview chatview; private void start() { chatview = transform.findchildbyname("chatview").getcomponent<chatview>(); ipendpoint ep = new ipendpoint(ipaddress.parse(serverip), serverport); //1). 创建对象并开启监听 serverlisten = new tcplistener(ep);//需要一个终结点 serverlisten.start(); //2.线程 thread = new thread(receiveclient); thread.start(); } private tcplistener serverlisten; private thread thread; //2.开启监听 //3.接收数据 显示 private void receiveclient() { tcpclient client = serverlisten.accepttcpclient(); //接收消息 //accepttcpclient() 接受挂起连接请求 networkstream stream = client.getstream(); //读取网络流到容器 byte[] date = new byte[1024]; //返回读了多少字节 //read读取消息 如果没有读取到 线程阻塞 //如果有多个客户端 要循环接收 将读到的信息放到线程中 int count; while((count=stream.read(date,0,date.length))>0) //count为0 表示客户端下线 { //解析 string msg = encoding.utf8.getstring(date); threadcrosshelper.instance.executeonmainthread(() => { showmessage(msg); }); } client.close();//关闭socket对象 自动释放流 } private void showmessage(string msg) { chatview.datasource.add(new chatline() { username = "anns", message = msg, time = datetime.now, type = chatlinetype.user, }); } //4.关闭 public void onapplicationquit() { thread.abort(); serverlisten.stop(); } }
中间发生连接请求过程(三次握手) , 断开连接(四次挥手)
三次握手
所谓三次握手就是建立tcp连接的过程,需要客户端和服务端总共发送3个包确认连接成功。在socket编程中,这一过程由客户端执行connect来触发。
简而言之:
第一次,客户端向服务端发出连接请求数据包。 “我想跟你聊会,可以吗?”
第二次,服务端向客户端发送同意连接和要求同步的数据包。“可以,什么时候啊?”
第三次,客户端再发出一个数据包确认服务器的同步要求。“就现在。”
四次挥手
所谓四次挥手就是终止tcp连接的过程,需要客户端和服务端总共发送4个包以确认连接断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发
简而言之:
第一次,客户端向服务端发送断开请求数据包。 “我都说完了,今天就到这吧”
第二次,服务端向客户端发送同意断开数据包。“恩,好的。”
第三次,服务端再向客户端发送断开请求数据报。“那我挂了啊?”
第四次,客户端再向服务端发送确认断开数据报。“拜拜”
此时服务端断开连接,客户端过会发现服务端没有回复,也断开连接。