那四个脚本需要放在服务器程序中去(BaseData、PlayerData、baseMsg、PlayerMsg)

主要修改的类:服务端启动类ServerSocket和序列化和反序列化类ClientSocket和Main函数类
序列化和反序列化类ClientSocket
首先修改的是ClientSocket:
需要修改成BaseMsg 的接收和发送
Send(string info)方法参数修改 socket.Send(Encoding.UTF8.GetBytes(info))
这两句代码修改成
Send(BaseMsg info)
socket.send(info.Writing())
接收:
需要将线程池中的方法
//先拿到消息ID
int msgID=BitConverter.ToInt32(result, 0)
BaseMsg msg = null
然后使用Switch进行判断ID 再进行反序列化
msg = new PlayerMsg()
msg.Reading(result,4)
再将
ThreadPool.QueueUserWorkItem(MsgHandle,Encoding.UTF8.GetString(result,0,receiveNum))
修改成 参数为BaseMsg类型数据
ThreadPool.QueueUserWorkItem(NewMsgHandle, msg)
NewMsgHandle方法中进行打印客户端发过来的消息
public void NewMsgHandle(object obj)
{
BaseMsg msg = (BaseMsg)obj
//进行判断 msg的结构类型
if(msg is PlayerMsg)
{
PlayerMsg playerMsg = (PlayerMsg)msg
Console.WriteLine(playerMsg.playerID)
Console.WriteLine(playerMsg.playerData.name)
Console.WriteLine(playerMsg.playerData.atk)
Console.WriteLine(playerMsg.playerData.lev)
}
}
服务端启动类ServerSocket
只需要修改广播方法
Broadcast(string info)将Broadcast(BaseMsg info)
主函数Program
修改广播发送数据方式

ClientSocket代码
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace TeachTcpExcise3qufenxiaoxi
{
class ClientSocket
{
private static int CLIENT_BEGIN_ID = 1; //初始ID等于1
public int clientID; //设置每个客户端的ID
public Socket socket;
//每次调用的时候会进行 自增 记录Socket
public ClientSocket(Socket socket)
{
this.clientID = CLIENT_BEGIN_ID;
this.socket = socket;
++CLIENT_BEGIN_ID;
}
/// <summary>
/// 可以从外部获取连接状态
/// </summary>
public bool isConnect => this.socket.Connected;
//封装 一些方法
//关闭
public void close()
{
if (socket != null)
return;
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = null;
}
//发送
public void send(BaseMsg info)
{
if (socket != null)
{
try
{
socket.Send(info.Writing());
}
catch (Exception e)
{
Console.WriteLine("发消息出错:"+e.Message);
close();
}
}
}
//接收
public void receive()
{
try
{
if (socket.Available > 0)
{
byte[] result = new byte[1024 * 5];
int receiveNum = socket.Receive(result);
//只接收字符串 线程池去接收处理发过来的消息
//ThreadPool.QueueUserWorkItem(MsgHandle,Encoding.UTF8.GetString(result,0,receiveNum));
//区分消息 接收消息 处理发过来的消息
//先拿到消息ID
int msgID=BitConverter.ToInt32(result, 0);
BaseMsg msg = null;
switch (msgID)
{
case 1001:
msg = new PlayerMsg();
msg.Reading(result,4); //解析 拿到数据 然后在 线程中进行处理
break;
}
ThreadPool.QueueUserWorkItem(NewMsgHandle, msg);
}
}
catch (Exception e)
{
Console.WriteLine("收消息出错:"+e.Message);
close();
}
}
//配套接收字符串 多线程
/*public void MsgHandle(object obj)
{
string str = (string)obj;
Console.WriteLine("收到客户端{0}发来的消息:{1}",this.socket.RemoteEndPoint,str);
}*/
public void NewMsgHandle(object obj)
{
BaseMsg msg = (BaseMsg)obj;
//进行判断 msg的结构类型
if(msg is PlayerMsg)
{
PlayerMsg playerMsg = (PlayerMsg)msg;
Console.WriteLine(playerMsg.playerID);
Console.WriteLine(playerMsg.playerData.name);
Console.WriteLine(playerMsg.playerData.atk);
Console.WriteLine(playerMsg.playerData.lev);
}
}
}
}
ServerSocket代码
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace TeachTcpExcise3qufenxiaoxi
{
class ServerSocket
{
//服务端Socket
public Socket socket;
//客户端连接的所有Socket
public Dictionary<int, ClientSocket> clientDic = new Dictionary<int, ClientSocket>();
//有待移除的客户端socket 避免 在foreach时直接从字典中移除 出现问题
private List<ClientSocket> delList = new List<ClientSocket>();
private bool isClose;
//开启服务器端
public void Start(string ip, int port, int num)
{
isClose = false;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
socket.Bind(ipPoint);
socket.Listen(num);
ThreadPool.QueueUserWorkItem(Accept);
ThreadPool.QueueUserWorkItem(Receive);
}
//关闭服务器端
public void Close()
{
isClose = true;
foreach (ClientSocket client in clientDic.Values)
{
client.close();
}
clientDic.Clear();
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = null;
}
//接受客户端连入
private void Accept(object obj)
{
while (!isClose)
{
try
{
//连入一个客户端
Socket clientSocket = socket.Accept();
ClientSocket client = new ClientSocket(clientSocket);
/* lock (clientDic)*/
clientDic.Add(client.clientID, client);
}
catch (Exception e)
{
Console.WriteLine("客户端连入报错" + e.Message);
}
}
}
//接收客户端消息
private void Receive(object obj)
{
while (!isClose)
{
if (clientDic.Count > 0)
{
/* lock (clientDic)
{
foreach (ClientSocket client in clientDic.Values)
{
client.receive();
}
//CloseDelListSocket();
}*/
//判断字典容器的客户端Socket是否存在
//进行遍历接受消息
foreach (ClientSocket client in clientDic.Values)
{
client.receive();
}
}
}
}
public void Broadcast(BaseMsg info)
{
lock (clientDic)
{
foreach (ClientSocket client in clientDic.Values)
{
client.send(info);
}
}
}
//添加待移除的 socket内容
public void AddDelSocket(ClientSocket socket)
{
if (!delList.Contains(socket))
delList.Add(socket);
}
/*////判断有没有 断开连接的 把其 移除
public void CloseDelListSocket()
{
//判断有没有 断开连接的 把其 移除
for (int i = 0; i < delList.Count; i++)
CloseClientSocket(delList[i]);
delList.Clear();
}
//关闭客户端连接的 从字典中移除
public void CloseClientSocket(ClientSocket socket)
{
lock (clientDic)
{
socket.close();
if (clientDic.ContainsKey(socket.clientID))
{
clientDic.Remove(socket.clientID);
Console.WriteLine("客户端{0}主动断开连接了", socket.clientID);
}
}
}*/
}
}
Program 主函数
{
internal class Program
{
static void Main(string[] args)
{
//在这主函数里面调用 谁的功能写在自身脚本中
ServerSocket socket = new ServerSocket();
socket.Start("127.0.0.1", 8080, 1024);
Console.WriteLine("服务器开启成功");
while (true)
{
string input = Console.ReadLine();
if (input == "Quit")
{
socket.Close();
}
else if (input.Substring(0, 2) == "B:")
{
//广播
if (input.Substring(2) == "1001")
{
PlayerMsg msg = new PlayerMsg();
msg.playerID = 99;
msg.playerData = new PlayerData();
msg.playerData.name = "王者";
msg.playerData.atk = 990;
msg.playerData.lev = 99;
socket.Broadcast(msg);
}
}
}
}
}
}