原文章:https://blog.csdn.net/u012234115/article/details/46481845
unity内部封装了一个很高层次的网络接口,不过有时候并不需要那么复杂的功能,只是想实现简单的TCP网络连接,可以在unity里面用C#写tcp socket。
以下TCP连接是同步模式。
建立两个unity工程,编写脚本。
服务端
-
using UnityEngine;
-
using System.Collections;
-
//引入库
-
using System.Net;
-
using System.Net.Sockets;
-
using System.Text;
-
using System.Threading;
-
-
public
class
TcpServer:
MonoBehaviour
-
{
-
//以下默认都是私有的成员
-
Socket serverSocket;
//服务器端socket
-
Socket clientSocket;
//客户端socket
-
IPEndPoint ipEnd;
//侦听端口
-
string recvStr;
//接收的字符串
-
string sendStr;
//发送的字符串
-
byte[] recvData=
new
byte[
1024];
//接收的数据,必须为字节
-
byte[] sendData=
new
byte[
1024];
//发送的数据,必须为字节
-
int recvLen;
//接收的数据长度
-
Thread connectThread;
//连接线程
-
-
//初始化
-
void InitSocket()
-
{
-
//定义侦听端口,侦听任何IP
-
ipEnd=
new IPEndPoint(IPAddress.Any,
5566);
-
//定义套接字类型,在主线程中定义
-
serverSocket=
new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
-
//连接
-
serverSocket.Bind(ipEnd);
-
//开始侦听,最大10个连接
-
serverSocket.Listen(
10);
-
-
-
-
//开启一个线程连接,必须的,否则主线程卡死
-
connectThread=
new Thread(
new ThreadStart(SocketReceive));
-
connectThread.Start();
-
}
-
-
//连接
-
void SocketConnet()
-
{
-
if(clientSocket!=
null)
-
clientSocket.Close();
-
//控制台输出侦听状态
-
print(
"Waiting for a client");
-
//一旦接受连接,创建一个客户端
-
clientSocket=serverSocket.Accept();
-
//获取客户端的IP和端口
-
IPEndPoint ipEndClient=(IPEndPoint)clientSocket.RemoteEndPoint;
-
//输出客户端的IP和端口
-
print(
"Connect with "+ipEndClient.Address.ToString()+
":"+ipEndClient.Port.ToString());
-
//连接成功则发送数据
-
sendStr=
"Welcome to my server";
-
SocketSend(sendStr);
-
}
-
-
void SocketSend(string sendStr)
-
{
-
//清空发送缓存
-
sendData=
new
byte[
1024];
-
//数据类型转换
-
sendData=Encoding.ASCII.GetBytes(sendStr);
-
//发送
-
clientSocket.Send(sendData,sendData.Length,SocketFlags.None);
-
}
-
-
//服务器接收
-
void SocketReceive()
-
{
-
//连接
-
SocketConnet();
-
//进入接收循环
-
while(
true)
-
{
-
//对data清零
-
recvData=
new
byte[
1024];
-
//获取收到的数据的长度
-
recvLen=clientSocket.Receive(recvData);
-
//如果收到的数据长度为0,则重连并进入下一个循环
-
if(recvLen==
0)
-
{
-
SocketConnet();
-
continue;
-
}
-
//输出接收到的数据
-
recvStr=Encoding.ASCII.GetString(recvData,
0,recvLen);
-
print(recvStr);
-
//将接收到的数据经过处理再发送出去
-
sendStr=
"From Server: "+recvStr;
-
SocketSend(sendStr);
-
}
-
}
-
-
//连接关闭
-
void SocketQuit()
-
{
-
//先关闭客户端
-
if(clientSocket!=
null)
-
clientSocket.Close();
-
//再关闭线程
-
if(connectThread!=
null)
-
{
-
connectThread.Interrupt();
-
connectThread.Abort();
-
}
-
//最后关闭服务器
-
serverSocket.Close();
-
print(
"diconnect");
-
}
-
-
// Use this for initialization
-
void Start()
-
{
-
InitSocket();
//在这里初始化server
-
}
-
-
-
// Update is called once per frame
-
void Update()
-
{
-
-
}
-
-
void OnApplicationQuit()
-
{
-
SocketQuit();
-
}
-
}
- 创建套接字
- 绑定套接字到ip和端口
- 侦听连接
- 接收连接
- 与客户端收发数据
- 返回等待另一连接
- 断开连接
把脚本挂到unity场景中某个物体上,比如camera,由于创建连接后有接收循环,所以要单独开一个线程,否则主线程会卡死。
客户端
-
using UnityEngine;
-
using System.Collections;
-
//引入库
-
using System.Net;
-
using System.Net.Sockets;
-
using System.Text;
-
using System.Threading;
-
-
public
class
TcpClient:
MonoBehaviour
-
{
-
string editString=
"hello wolrd";
//编辑框文字
-
-
Socket serverSocket;
//服务器端socket
-
IPAddress ip;
//主机ip
-
IPEndPoint ipEnd;
-
string recvStr;
//接收的字符串
-
string sendStr;
//发送的字符串
-
byte[] recvData=
new
byte[
1024];
//接收的数据,必须为字节
-
byte[] sendData=
new
byte[
1024];
//发送的数据,必须为字节
-
int recvLen;
//接收的数据长度
-
Thread connectThread;
//连接线程
-
-
//初始化
-
void InitSocket()
-
{
-
//定义服务器的IP和端口,端口与服务器对应
-
ip=IPAddress.Parse(
"127.0.0.1");
//可以是局域网或互联网ip,此处是本机
-
ipEnd=
new IPEndPoint(ip,
5566);
-
-
-
//开启一个线程连接,必须的,否则主线程卡死
-
connectThread=
new Thread(
new ThreadStart(SocketReceive));
-
connectThread.Start();
-
}
-
-
void SocketConnet()
-
{
-
if(serverSocket!=
null)
-
serverSocket.Close();
-
//定义套接字类型,必须在子线程中定义
-
serverSocket=
new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
-
print(
"ready to connect");
-
//连接
-
serverSocket.Connect(ipEnd);
-
-
//输出初次连接收到的字符串
-
recvLen=serverSocket.Receive(recvData);
-
recvStr=Encoding.ASCII.GetString(recvData,
0,recvLen);
-
print(recvStr);
-
}
-
-
void SocketSend(string sendStr)
-
{
-
//清空发送缓存
-
sendData=
new
byte[
1024];
-
//数据类型转换
-
sendData=Encoding.ASCII.GetBytes(sendStr);
-
//发送
-
serverSocket.Send(sendData,sendData.Length,SocketFlags.None);
-
}
-
-
void SocketReceive()
-
{
-
SocketConnet();
-
//不断接收服务器发来的数据
-
while(
true)
-
{
-
recvData=
new
byte[
1024];
-
recvLen=serverSocket.Receive(recvData);
-
if(recvLen==
0)
-
{
-
SocketConnet();
-
continue;
-
}
-
recvStr=Encoding.ASCII.GetString(recvData,
0,recvLen);
-
print(recvStr);
-
}
-
}
-
-
void SocketQuit()
-
{
-
//关闭线程
-
if(connectThread!=
null)
-
{
-
connectThread.Interrupt();
-
connectThread.Abort();
-
}
-
//最后关闭服务器
-
if(serverSocket!=
null)
-
serverSocket.Close();
-
print(
"diconnect");
-
}
-
-
// Use this for initialization
-
void Start()
-
{
-
InitSocket();
-
}
-
-
void OnGUI()
-
{
-
editString=GUI.TextField(
new Rect(
10,
10,
100,
20),editString);
-
if(GUI.Button(
new Rect(
10,
30,
60,
20),
"send"))
-
SocketSend(editString);
-
}
-
-
// Update is called once per frame
-
void Update()
-
{
-
-
}
-
-
//程序退出则关闭连接
-
void OnApplicationQuit()
-
{
-
SocketQuit();
-
}
-
}
- 创建套接字
- 向服务器发出连接请求
- 和服务器通信
- 断开连接
同样把脚本挂到场景某个物体中,创建连接和接收循环都放在
新开的线程里面,在界面上放一个文字编辑框和一个button用于给服务端发消息。
测试
程序实现的功能为,当一个新的客户端连接到服务端时,服务端控制台输出相关信息,并向客户端发送初始信息,客户端每次向服务端的信息由服务端接收后添加一段字符串再发送回来。