unity应用之socket连接–步骤三同一工程中运行
将服务端和客户端都在unity中实现。
注意:服务端需要等待,即包含阻塞方法,unity中所有方法都是一个主线程中运行,所以,如果以如果直接在start中调用启动服务器的方法,unity会直接卡死的,所以我们就自己起一个线程去搞服务端部分。
unity中起线程后要清楚两点:
1、monoBehavior类中的方法尽量别用了,会出现不可预知的bug。
2、自己起的线程,系统不会掺和,自己找个合适的地方再把他kill掉。
下面的代码是在程序结束时杀掉线程,起线程就像拉屎,完事一定要记得自己擦,系统不会给你擦,经测试不擦第二次启动unity会无响应。
简单实现了从客户端发送一个字符串的包到服务端,服务端接收后并打印出来,代码全部贴出来:
在同一个unity工程中,新建两个脚本,一个是服务端,一个是客户端,均须挂在到场景中的空物体上,不然连接不上。
客户端代码:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;
public class SocketClient : MonoBehaviour
{
void Start()
{
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
Client();
}
}
TcpClient client;
private void Client()
{
client = new TcpClient();
try
{
client.Connect(IPAddress.Parse("192.168.1.104"), 10001);//同步方法,连接成功、抛出异常、服务器不存在等之前程序会被阻塞
}
catch (Exception ex)
{
Debug.Log("客户端连接异常:" + ex.Message);
}
Debug.Log("LocalEndPoint = " + client.Client.LocalEndPoint + ". RemoteEndPoint = " + client.Client.RemoteEndPoint);
//客户端发送数据部分
for (int i = 0; i < 2; i++)
{
try
{
string msg = "hello server i am No " + i;
NetworkStream streamToServer = client.GetStream();//获得客户端的流
byte[] buffer = Encoding.Unicode.GetBytes(msg);//将字符串转化为二进制
streamToServer.Write(buffer, 0, buffer.Length);//将转换好的二进制数据写入流中并发送
Debug.Log("发出消息:" + msg);
}
catch (Exception ex)
{
Debug.Log("服务端产生异常:" + ex.Message);
}
}
}
}
服务端代码块:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System;
/// <summary>
/// scoket服务器监听端口脚本
/// </summary>
public class SocketServer : MonoBehaviour
{
private Thread thStartServer;//定义启动socket的线程
void Start()
{
thStartServer = new Thread(StartServer);
thStartServer.Start();//启动该线程
//thStartServer = new Thread(OnApplicationQuit);
//thStartServer.Start();
}
void Update()
{
}
private void StartServer()
{
const int bufferSize = 8792;//缓存大小,8192字节
IPAddress ip = IPAddress.Parse("192.168.1.104");
TcpListener tlistener = new TcpListener(ip, 10001);
tlistener.Start();
Console.WriteLine("Socket服务器监听启动......");
TcpClient remoteClient = tlistener.AcceptTcpClient();//接收已连接的客户端,阻塞方法
Debug.Log("客户端已连接!local:" + remoteClient.Client.LocalEndPoint + "<---Client:" + remoteClient.Client.RemoteEndPoint);
NetworkStream streamToClient = remoteClient.GetStream();//获得来自客户端的流
do
{
try //直接关掉客户端,服务器端会抛出异常
{
//接收客户端发送的数据部分
byte[] buffer = new byte[bufferSize];//定义一个缓存buffer数组
int byteRead = streamToClient.Read(buffer, 0, bufferSize);//将数据搞入缓存中(有朋友说read()是阻塞方法,测试中未发现程序阻塞)
if (byteRead == 0)//连接断开,或者在TCPClient上调用了Close()方法,或者在流上调用了Dispose()方法。
{
Debug.Log("客户端连接断开......");
break;
}
string msg = Encoding.Unicode.GetString(buffer, 0, byteRead);//从二进制转换为字符串对应的客户端会有从字符串转换为二进制的方法
Debug.Log("接收数据:" + msg + ".数据长度:[" + byteRead + "byte]");
}
catch (Exception ex)
{
Debug.Log("客户端异常:" + ex.Message);
break;
}
}
while (true);
}
void OnApplicationQuit()
{
thStartServer.Abort();//在程序结束时杀掉线程,想起以前老谢给我讲的,起线程就像拉屎,完事一定要记得自己擦,系统不会给你擦,经测试不擦第二次启动unity会无响应
}
}