经过一段时间的学习,对于TCP/IP协议有了一定的认识,大概知道了TCP协议通信的原理,接下来主要实现用TcpClient、TcpListener两个封装类和stream来实现一个小的demo:用vs建一个工程作为服务器,然后用Unity引擎作为客户端,实现客户端和服务器,客户端和客户端之间的通信。
由于入坑试验多次,这里强调一下通信时候的数据转换,当在客户端发送信息的时候,会将用户输入的字符串转为byte型数组(要通过NetworkStream stream这个对象写入)
代码块一:
void SendMessage(string myWrite) {
byte[] data = Encoding.UTF8.GetBytes(myWrite);
stream.Write(data, 0, data.Length);
}
服务器端通过流stream来读取数据,并且将数据重新转换为字符串:
代码块二:
byte[] data = new byte[1024];
int length = stream.Read(data, 0, data.Length);
string message = Encoding.UTF8.GetString(data, 0, length);
转换为字符串后就可以在服务器端打印输出了,然后需要再次将字符串数据转为byte[]数组,重新传回客户端
代码块三:(注意!!!在服务器端一定要将客户端读取的byte数组数据先转为字符串,再将字符串重新转为byte[]数组写入到客户端,至于原因,前面踩过坑,发现,如果直接将客户端读取的byte数组写入到客户端,在Unity的UGUI的文本框显示会出现问题,UGUI只会显示用户输入的第一条数据。总之,这一过程必不可少)
public void SendMessage(string message) {
byte[] data = Encoding.UTF8.GetBytes(message);
stream.Write(data, 0, data.Length);
}
然后在客户端读取服务器写入过来的数据,将其用byte数组存放,并转为string字符串
代码块四:
byte[] data = new byte[1024];
int length = stream.Read(data, 0, data.Length);
message = Encoding.UTF8.GetString(data, 0, length);
最后将字符串通过Unity引擎的UGUI和基本代码显示到Unity场景中
完整代码如下
服务器端(用vs创建一个工程)由一个主方法和自定义类组成:
额外添加命名空间:using System.Net; using System.Net.Sockets; using System.Threading;
主方法如下:
class Program
{
public static List
public static void BroadcastMessage(string message)
{
List
foreach (var client in ls)
{
if (client.client.Connected)
{
client.SendMessage(message);
}
else
{
nols.Add(client);
}
}
foreach (var i in nols)
{
ls.Remove(i);
}
}
static void Main(string[] args)
{
//1.创建一个TCPListener对象,实例化绑定了IP和端口号
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Parse("192.168.1.101"), 7788));
//2.开始侦听
listener.Start();
Console.WriteLine("已开启服务器...");
TcpClient client;
NetworkStream stream;
byte[] data = new byte[1024]; //data作为一个容器用来接收
//读取流里面的数据,存放到data的0索引位置,每次最大读取1024个字节
while (true)
{
//3.等待客户端连接
client = listener.AcceptTcpClient();
Console.WriteLine("一个客户端已连接");
//4.取得客户端发送过来的数据
stream = client.GetStream();
ClientStream clientStream = new ClientStream(stream, client);
ls.Add(clientStream);
}
stream.Close();
client.Close();
listener.Stop();
Console.ReadKey();
}
}
自定义类如下:
class ClientStream
{
private Thread t;
private NetworkStream stream;
public TcpClient client;
public ClientStream(NetworkStream stream, TcpClient client) {
this.stream = stream;
this.client = client;
t = new Thread(ReceiveMessage);
t.Start();
}
private void ReceiveMessage() {
while (true)
{
if (client.Connected == false)
{
Console.WriteLine("客户端断开连接");
stream.Close();
break; //跳出循环,终止线程的执行
}
byte[] data = new byte[1024];
int length = stream.Read(data, 0, data.Length);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("收到了消息:" + message);
Program.BroadcastMessage(message);
}
}
public void SendMessage(string message) {
byte[] data = Encoding.UTF8.GetBytes(message);
stream.Write(data, 0, data.Length);
}
}
客户端脚本(创建一个Unity项目,需额外添加命名空间using System.Net; using System.Net.Sockets; using System.Text;
using System.Threading;):
public class ClientTest : MonoBehaviour {
public Text textContainer;
public InputField text;
private string address = "192.168.1.101";
private int port = 7788;
private TcpClient client;
private NetworkStream stream;
private Thread t;
private string message;
// Use this for initialization
void Start () {
ConnectToServer();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Return))
{
OnSendButtonClick();
}
if (message != "" && message != null)
{
textContainer.text += "\n" + message;
Debug.Log("message2:" + message);
Debug.Log("文本框2:" + textContainer.text);
message = "";
}
}
//客户端的连接
void ConnectToServer() {
client = new TcpClient(address, port);
Debug.Log("client.Available:" + client.Available);
//if (client.Available == 0)
// Debug.Log("服务器不存在");
stream = client.GetStream();
Debug.Log("客户端连接");
t = new Thread(ReceiveMessage);
t.Start();
}
//客户端发送消息
void SendMessage(string myWrite) {
byte[] data = Encoding.UTF8.GetBytes(myWrite);
stream.Write(data, 0, data.Length);
}
//客户端接收消息
void ReceiveMessage() {
while (true)
{
if (client.Connected == false)
{
break;
}
byte[] data = new byte[1024];
int length = stream.Read(data, 0, data.Length);
message = Encoding.UTF8.GetString(data, 0, length);
Debug.Log("从服务器受到了:"+message);
}
}
//按钮侦听函数
public void OnSendButtonClick() {
if (text.text != null && text.text != "" && client.Connected) {
string myWrite= text.text;
SendMessage(myWrite);
text.text = "";
}
}
void OnDestroy() {
stream.Close();
client.Close();
}
}
最后先编译vs这边的程序,即启动服务器,
然后运行Unity,即启动客户端,
也可以将Unity项目打包发布PC端,这样就可以有多个客户端了
以上只是一个小的demo,望各位大佬不吝赐教!!!