TCP
(1).建立一个套接字(Socket)
(2).绑定服务器端IP地址及端口号–服务器端
(3).利用Listen()方法开启监听–服务器端
(4).利用Accept()方法尝试与客户端建立一个连接–服务器端
(5).利用Connect()方法与服务器建立连接–客户端
(6).利用Send()方法向建立连接的主机发送消息
(7).利用Recive()方法接受来自建立连接的主机的消息(可靠连接)
服务器端绑定IP:端口号后,局域网内的计算机都可以与这个IP进行通信,都可以跟这个计算机做通信
客户端发起建立连接的请求,客户端的IP:端口号要与服务器端绑定的IP:端口号一致才能连接
客户端
using System.Text;
using System.Net.Sockets;
using System.Net;
using UnityEngine;
using UnityEngine.UI;
using System.Threading;
public class _GameManager : MonoBehaviour
{
public string ipAdress = "10.10.6.59";//需要连接的服务器的地址
public int port = 7788;//需要连接的服务器设置的端口
public InputField textInput;
public Text textShow;
private Socket clientSocket;
private Thread t;
private byte[] data = new byte[1204];//数据容器
private string message="";//消息容器,存储广播过来的消息
void Start()
{
ConnectServer();
}
// Update is called once per frame
void Update()
{
if (message !=null&&message !="")
{
textShow.text +="\n" +message;//显示消息
message = "";//清空消息
}
}
void ConnectServer()
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//跟服务器端建立连接,服务器端绑定的IP地址就是需要连接的,客户端的ipAdress不一致就连接不上
clientSocket.Connect(new IPEndPoint(IPAddress .Parse (ipAdress), port));//通过IP+端口号定位一个要连接的服务器端
//创建一个新的线程 用来接收收消息
t = new Thread(ReceiveMessage);
t.Start();
}
private void ReceiveMessage()
{
while (true)
{
if (clientSocket.Poll(10, SelectMode.SelectRead))
{
//clientSocket.Close();
//Debug.Log("连接已断开,客户端不再接收消息");
break;
}
int length = clientSocket.Receive(data);//存储字节数据于data中,并返回长度
message = Encoding.UTF8.GetString(data, 0, length);
}
}
void _SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);//发送消息
}
public void OnSendButtonClick()
{
string messageText = textInput.text;//获取输入区输入的消息
_SendMessage(messageText);//发送消息
textInput.text = "";//发送消息后,清空输入区的消息
}
private void OnDestroy()//Unity按下停止按钮后,关闭程序前执行OnDestroy()函数
{
//clientSocket.Shutdown(SocketShutdown.Both);
//Debug.Log("连接已断开,客户端不再接收消息");
t.Abort();//关闭线程,若不关闭,结束时会输出一个错误:一个封锁操作被对 WSACancelBlockingCall 的调用中断。
clientSocket.Close();//关闭连接
}
}
服务器端Client类
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCP服务器端
{
class Client
{
private Socket clientSocket;
private Thread t;
private byte[] data=new byte[1024];//数据容器
public Client (Socket s)//用来做通信,在Program类里传入:Client client = new Client(clientSocket);
{
clientSocket = s;
//启动一个线程 处理客户端的数据接收
t = new Thread(ReceiveMessage);
t.Start();
}
private void ReceiveMessage()
{
while (true)//一直接受客户端的信息
{
if (clientSocket .Poll (10,SelectMode.SelectRead))//如果连接已断开,跳出循环
{
clientSocket.Close();
//Console.WriteLine("连接已断开,服务器不再接收消息");
break;
}
int length=clientSocket.Receive(data);//接收字符数组,获取长度
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);//对字符串编码,把字符串转化为字节数组
clientSocket.Send(data);//向客户端发送
}
public bool _Connected
{
get { return clientSocket.Connected; }//客户端是否连接
}
}
}
服务器端
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
namespace TCP服务器端
{
class Program
{
static List<Client> clientList = new List<Client>();
/// <summary>
/// 广播消息,向多个客户端发送消息
/// </summary>
/// <param name="message"></param>
public static void BroadcastMessage(string message)
{
var notConnectedList = new List<Client>();
foreach (var client in clientList)
{
if(client ._Connected )
{
client._SendMessage(message);
}
else
{
notConnectedList.Add(client);
}
}
foreach (var temp in notConnectedList)
{
clientList.Remove(temp);
}
}
static void Main(string[] args)
{
//1.创建Socket
Socket tcpSever = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.绑定IP与端口号 10.10.6.59
tcpSever.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"),7788));//IPEndPoint是对IP+端口号做了一层封装的类
//3.开始监听,等待客户端做连接
tcpSever.Listen(0);//参数是最大连接数
Console.WriteLine("开始监听");
Console.WriteLine("Sever Running");
while (true)
{
//使用返回的Socket做通信
Socket clientSocket = tcpSever.Accept();//暂停当前线程,直到有一个客户端连接过来,之后进行下面的代码
Console.WriteLine("一个客户端已连接");
Client client = new Client(clientSocket);//把与每个客户端做通信(收发消息)的逻辑放到Client类里处理
clientList.Add(client);//添加客户端
}
}
}
}
添加一个Image与一个Text,Image作为Text的背景。
添加一个InputField作为输入框。
添加一个按钮。记得注册点击事件。
添加一个空物体命名为_GameManager,挂载客户端脚本。
UDP
不需要连接过程,直接根据 IP:端口 收发数据
1.只能收发一次
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDP客户端
{
class Program
{
static void Main(string[] args)
{
//创建socket
Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//发送数据
EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788);
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, serverPoint);
Console.ReadKey();
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace UDP服务器
{
class Program
{
static void Main(string[] args)
{
//1.创建socket
Socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//2.绑定IP跟端口号
udpServer.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788));
//3.接收数据
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);//IP指定为Any,端口指定为0,后面ReceiveFrom方法会修改
byte[] data = new byte[1024];
int length=udpServer.ReceiveFrom(data, ref remoteEndPoint);//这个方法会把客户端的IP与端口号放到第二个参数,ref表示ReceiveFrom方法可以修改remoteEndPoint的属性
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("从IP:" + (remoteEndPoint as IPEndPoint).Address + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据:" + message);
udpServer.Close();
Console.ReadKey();
}
}
}
2.多次循环收发
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDP客户端
{
class Program
{
static void Main(string[] args)
{
//创建socket
Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
while (true)
{
EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788);
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, serverPoint);
}
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace UDP服务器
{
class Program
{
static Socket udpServer;
static void Main(string[] args)
{
//1.创建socket
udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//2.绑定IP跟端口号
udpServer.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788));
//3.接收数据
new Thread(ReceiveMessage) { IsBackground = true }.Start();
//udpServer.Close();
Console.ReadKey();
}
static void ReceiveMessage()
{
while (true)
{
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);//IP指定为Any,端口指定为0,后面ReceiveFrom方法会修改
byte[] data = new byte[1024];
int length = udpServer.ReceiveFrom(data, ref remoteEndPoint);//这个方法会把客户端的IP与端口号放到第二个参数,ref表示ReceiveFrom方法可以修改remoteEndPoint的属性
//会暂停等待接收数据,只有接收到了数据才会执行下面的代码
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("从IP:" + (remoteEndPoint as IPEndPoint).Address + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据:" + message);
}
}
}
}