上一节中对Socket创建连接注释的挺清楚了,这里就不会注释那么清楚了,要是有不太懂的地方可以参考上一节。
这里用一个unity创建一个简单的聊天室
还是先贴服务器的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;//EndPoint的命名空间
using System.Net.Sockets;//Socket的命名空间
using System.Text;
using System.Threading.Tasks;
namespace unity聊天室_创建tcp服务器端_01
{
/*
* 服务器端
* 创建socket
* 绑定ip和端口号
* 设置监听
* 等待客户端连接//把这个等待客户端连接的方法放到While中
* 由于等待到客户端连接,要返回一个Socket类型的对象,将来是要用这个对象和客户端通信的
* 所以创建一个包含Socket 的类,该类中包含了和库户端通信的方法
* 用一个List把创建的类保存起来,(会有很多客户端连接过来,所以用list比较方便)
* 用list保存起来可以很方便的给所有连接的客户端发送消息
*/
class Program
{
static List<Client> clientList = new List<Client>();
/// <summary>
/// 广播消息
/// </summary>
/// <param name="message"></param>
public static void BroadcastMessage(string message)
{
List<Client> notConnctedList = new List<Client>();
foreach (var client in clientList)
{
if (client.Connected)
{
client.SendMessage(message);//连接的客户端发送消息
}
else
{
notConnctedList.Add(client);//没有连接的客户端添加到一个没连接的list里,方便一会把没有连接的删除
}
}
foreach (var item in notConnctedList)
{
clientList.Remove(item);//把没有连接的客户端删除,
}
}
static void Main(string[] args)
{
//创建Socket
Socket tcpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//绑定ip和端口号
tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.35.36"),7788));//这个ip地址根据自己的电脑确定
//设置监听
tcpServer.Listen(100);
Console.WriteLine("连接中...");
while (true)
{
//等待连接,返回一个Socket类型,用这个Socket和连接到的客户端通信
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("一个客户端连接过来 !!!");
//把与每个客户端通信的逻辑(收发消息)放到Client类里进行处理
Client client = new Client(clientSocket);
clientList.Add(client);
}
}
}
}
//下面是服务器端Client类的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace unity聊天室_创建tcp服务器端_01
{
/// <summary>
/// 用来跟客户端做通信
/// </summary>
class Client
{
private Socket clientSocket;//用这个socket和客户端通信
private Thread t;//定义一个线程,用来处理客户端的数据接收
private byte[] data = new byte[1024];//这是一个数据容器
//这个构造在创建Client对象的时候调用(会传递一个Socket对象,就是用这个对象和不同客户端通信的) 顺便开启一个线程接收客户端发来的消息
public Client(Socket s)
{
clientSocket = s;
//启动一个线程处理客户端的数据接收
t = new Thread(ReceiveMessage);
t.Start();
}
/// <summary>
/// 接收数据,并把接收到的消息广播给各个客户端
/// </summary>
private void ReceiveMessage()
{
//一直接收客户端的数据
while (true)
{
//在接收数据之前,判断一下socket连接是否断开
if (clientSocket.Poll(10,SelectMode.SelectRead))
{
clientSocket.Close();//关闭当前的连接
break;
}
int length = clientSocket.Receive(data);//接收数据返回int类型,表示接收了多少字节
string message = Encoding.UTF8.GetString(data, 0, length);
//(服务器端在)接收到数据的时候 要把这个数据分发到客户端
Console.WriteLine("收到了消息:"+ message);
Program.BroadcastMessage(message);//广播方法 自己写
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="message"></param>
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
//判断是否连接,
public bool Connected
{
get { return clientSocket.Connected; }
}
}
}
下面是客户端的代码
先编辑好Unity的聊天界面
using UnityEngine;
//using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Text;
using UnityEngine.UI;
using System.Threading;
public class ChatManger : MonoBehaviour {
public string ipaddress = "192.168.35.36";
public int port = 7788;
private Socket clinetSocket;
public InputField uiInput;
public Text uiLable;
private Thread t;
private byte[] data = new byte[1024];//数据容器
private string message = "";//用来接收传递过来的消息(服务器广播的消息)
// Use this for initialization
void Start () {
ConnectToServer();
}
// Update is called once per frame
void Update () {
if (message != null && message != "")
{
uiLable.text += "\n" + message;
message = "";//赋值完了清空message
}
}
/// <summary>
/// 建立数据连接
/// </summary>
void ConnectToServer()
{
//创建socket
clinetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//跟服务器端建立连接
clinetSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
//为了方便接收服务器广播的消息,在创建socket的时候在创建一个新的线程用来接收消息
t = new Thread(ReceiveMessage);
t.Start();
}
/// <summary>
/// 这个线程方法用来循环接收消息
/// </summary>
private void ReceiveMessage()
{
while (true)
{
if (clinetSocket.Connected == false)
{
break;
}
int length = clinetSocket.Receive(data);//接收服务器发来的数据
message = Encoding.UTF8.GetString(data, 0, length);
//uiLable.text += "\n" + message;//unity中不允许在另一个线程操作unity中的组件
}
}
/// <summary>
/// 发送数据的方法
/// </summary>
/// <param name="message"></param>
void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clinetSocket.Send(data);//发送给服务器
}
/// <summary>
/// 点击发送时调用的方法
/// </summary>
public void OnSendButtonClick()
{
string value = uiInput.text;
SendMessage(value);
uiInput.text = "";
}
//当程序结束是关闭连接,clinetSocket
void OnDestroy()
{
clinetSocket.Shutdown(SocketShutdown.Both);//关闭(枚举)
clinetSocket.Close();//关闭连接
}
}