简而言之,TCP通讯原理大家可以从各种网络文献上找到,这里不做赘述。
只提出C#实现TCP通讯的一般方法和常用代码工具供第一次接触TCP通讯的玩家参考,老玩家绕道。。。
为了方便大家理解我的代码,会适当提及通讯远离。
1、建立服务端,TCP连接的基本:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Drawing.Imaging;
using System.Drawing;
using System.Net;
using System.IO;
using System.Threading;
public class DeviceSocket : MonoBehaviour
{
private Socket Soc_Temp0;
private TcpListener tcpLister0;
Thread Thread_Start0;
Thread Thread_getData0;
Thread Thread_sendData0;
bool live0 = true;
string send_Mes0 = "";
private string IPsend;
public Text LocalIP;
struct sendDate0
{
public byte[] fssize0;
};
private sendDate0 Msg0;
void Start()
{
GetAddressIP();
}
void Update()
{
}
void Disable()
{
live0 = false;
live1 = false;
live2 = false;
Soc_Temp0.Close();
Soc_Temp1.Close();
Soc_Temp2.Close();
Thread_Start0.Abort();
Thread_Start1.Abort();
Thread_Start2.Abort();
}
//获取本机IP
void GetAddressIP()
{
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
IPsend = _IPAddress.ToString();
}
}
LocalIP.text = IPsend;
}
/// <summary>
/// 开启服务器0
/// </summary>
public void begin0()
{
try
{
tcpLister0 = new TcpListener(IPAddress.Any, 8080);
tcpLister0.Start();
}
catch (Exception ex)
{
Debug.Log("ex=" + ex);
}
Thread_Start0 = new Thread(Start0);
Thread_Start0.IsBackground = true;
Thread_Start0.Start();
Debug.Log("线程开启状态Thread_Start0=" + Thread_Start0.ThreadState);
Debug.Log("线程开启状态Thread_Start0=" + Thread_Start0.IsAlive);
}
//TCP连接 并且 开启一个函数线程专门用于接收数据
void Start0()
{
while (live0)
{
try
{
if (tcpLister0.Pending())
{
Soc_Temp0 = tcpLister0.AcceptSocket();
Thread_getData0 = new Thread(getData0);
Thread_getData0.IsBackground = true;
Thread_getData0.Start();
Debug.Log("线程接收状态Thread_getData=" + Thread_getData0.ThreadState);
Debug.Log("线程接收状态Thread_getData=" + Thread_getData0.IsAlive);
}
}
catch (Exception e)
{
Debug.Log(e.Data.ToString());
Soc_Temp0.Close();
Soc_Temp0 = null;
live0 = false;
tcpLister0.Stop();
Thread_getData0.Abort();
}
}
}
//接收数据线程函数
void getData0()
{
while (live0)
{
try
{
Debug.Log("开始接收!!!");
//这里开辟了1M的字节空间 也就是一次图片的传输最大是1M大小
byte[] bytes = new byte[8];
Soc_Temp0.Receive(bytes, bytes.Length, SocketFlags.None);
// Debug.Log(System.Text.Encoding.ASCII.GetString(bytes));
for (int i = 0; i < 2; i++)
{
Debug.Log("System.Convert.ToString(buffer[" + i + "],2)=" + System.Convert.ToString(bytes[i], 2));
}
}
catch (Exception e)
{
Debug.Log(e.Data.ToString());
live0 = false;
Soc_Temp0.Close();
Soc_Temp0 = null;
Thread_getData0.Abort();
}
}
}
public void SendDate0()
{
// //发送数据
byte[] bytes = new byte[8];
bytes[0] = 3;
bytes[1] = 5;
Soc_Temp0.Send(bytes);
}
catch (SocketException e)
{
Debug.Log(e.Data.ToString());
fs.Close();
Soc_Temp0.Shutdown(System.Net.Sockets.SocketShutdown.Send);
Soc_Temp0.Close();
Soc_Temp0 = null;
}
}
2、下面是客户端脚本,用于连接服务端,注:客户端与服务端连接需要客户端知道服务端IP地址和端口号,1个客户端只能同时连接1个服务端,而服务端可以不限制连接进来的客户端数量。
下面是客户端脚本:
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
using UnityEngine.UI;
using System.Drawing.Imaging;
using System.Drawing;
public class client : MonoBehaviour
{
public IPAddress IPAddress0;
private string ClientIP0;
public Text ClientIPText0;
private string IPsend;
public Text LocalIP;
public Socket clientMsg0;
Thread Thread_Start0;
Thread GetDate_Start0;
public bool live0 = true;
public RawImage raw0;
private bool accepted0 = false;
private string path0;
public Text SendDateText0;
public Text IP0;
public Text COM0;
private bool HadConnect0 = false;
private string ImageUrl0 = "";
private int ImageNumber0 = 0;
private bool AcceptImage0 = false;
private float AcceptGap0 = 0;
private byte[] byte0;
private int ThreadNumber = 0;
void OnDisable()
{
tcpLister0.Stop();
}
void Awake()
{
Screen.SetResolution(1280, 720, false);
GetAddressIP();
Application.runInBackground = true;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
void Update()
{
ReceiveDate();
}
void GetAddressIP()
{
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
IPsend = _IPAddress.ToString();
}
}
LocalIP.text = IPsend;
}
public void TCPConnect0()
{
try
{
IPEndPoint ipendpiont = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 8080);
clientMsg0 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientMsg0.Connect(ipendpiont);
Thread_Start0 = new Thread(TCPListener0);
Thread_Start0.IsBackground = true;
Thread_Start0.Start();
live0 = true;
}
catch (Exception ex)
{
Debug.Log(ex);
ConnectState0 = "连接失败!!!";
}
}
/// <summary>
/// TCP接收数据
/// </summary>
void TCPListener0()
{
while (live0)
{
try
{
IPAddress0 = ((IPEndPoint)clientMsg0.RemoteEndPoint).Address; //获取连接的IP
ClientIP0 = IPAddress0.ToString();
Debug.Log("IPAddress0=" + IPAddress0);
byte0 = new byte[8];
clientMsg0.Receive(byte0, byte0.Length, SocketFlags.None);
for (int i = 0; i < 2; i++)
{
Debug.Log("System.Convert.ToString(buffer[" + i + "],2)=" + System.Convert.ToString(byte0[i], 2));
}
}
catch (Exception e)
{
Debug.Log(e.Data.ToString());
Debug.Log("e=" + e);
clientMsg0.Close();
clientMsg0 = null;
Thread_Start0.Abort();
}
}
}
public void QuitGame()
{
Application.Quit();
tcpLister0.Stop();
}
}
3、上面就是TCP连接的基本连接方法,TCP连接稳定不丢包,但是速度相较于UDP慢,如有问题欢迎留言讨论。