服务器(基础版)
服务器 端口号必须和服务器一致不然无法链接
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Google.Protobuf;
using MyGame;
namespace FWQ1
{
//登陆结构体
public struct loginMessage
{
public string strUserName;
public string strPassword;
}
struct chatMessage
{
public string chtMsg;
}
class YBNetManager : Singelton<YBNetManager>
{
public int num;
//创建Sockets;
public Socket m_socket;
//创建一个存储客户端的容器
public List<Client> m_clients = new List<Client>();
public void init()
{
//实例化 //互联网家庭地址 接口类型是流类型 协议是Tcp
m_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp) ;
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, 3000);
m_socket.Bind(iPEndPoint);//绑定接口的网络地址
m_socket.Listen(100);//最多同时接受100个链接不超过1024
//在以下代码等待接收服务器的消息
m_socket.BeginAccept(OnAccept,null);//开始接受并等待链接
Console.WriteLine("服务器启动了");
}
//顺序3
//回调函数客户端
private void OnAccept(IAsyncResult ar)
{
Client clt = new Client();//创建一个客户端
clt.m_socket = m_socket.EndAccept(ar);//获取客户端的Socket
IPEndPoint iPEnd = clt.m_socket.RemoteEndPoint as IPEndPoint;//获取端口和IP
clt.m_strIP = iPEnd.Address + "" + iPEnd.Port;//IP和地址
Console.WriteLine(clt.m_strIP+"链接成功");//打印链接成功提示
clt.m_socket.BeginReceive(clt.m_data,0,clt.m_data.Length,SocketFlags.None,OnReceive,clt);//接收客户端传来的数据
m_clients.Add(clt);//添加到容器
m_socket.BeginAccept(OnAccept, null);//继续监听,有的话继续,没有的话跳过
}
//顺序4
//接收的数据操作
private void OnReceive(IAsyncResult ar)
{
Client client = ar.AsyncState as Client;//通过系统ar方法获取上文clt的值
int len = client.m_socket.EndReceive(ar);//获取数据长度
if (len>0)//大于0证明有东西
{
byte[] data = new byte[len];
Buffer.BlockCopy(client.m_data,0,data,0,len); //这个方法给data赋值
//解析数据
client.m_stream = client.m_stream.Concat(data).ToArray();
while (client.m_stream.Length>2)//至少要大于两个字节
{
//取长度
ushort bodylen = BitConverter.ToUInt16(client.m_stream,0);//取出前面两个字节为包的长度
int allLen = bodylen + 2;//整个包的长度
if (client.m_stream.Length>=allLen)//最少要有一个包,也可能有很多个包
{
//取出一个包数据
byte[] oneData = new byte[bodylen];
//把包里的数据拷贝出来//从第第三个字节开始取,放入变量的第零位,变量的长度
Buffer.BlockCopy(client.m_stream,2, oneData, 0, oneData.Length);//取出ID和包的内容
//取ID;
int id = BitConverter.ToInt32(oneData, 0);
//取出包体内容
byte[] body = new byte[bodylen-4];//把ID的长度去掉剩下的是包长
Buffer.BlockCopy(oneData,4,body,0,body.Length);
//顺序5 把数据通过消息中心传到对应的 业务
//消息中心
MessageManager.instance.OnSendListen(id,body,client);
int syLen = client.m_stream.Length - allLen;//可能传来很多包 所以总长度减去当前解析包的长度获取剩余长度
//解析完的包移除掉
if (syLen>0)//数据没有解析完成数据往前移动
{
byte[] syData = new byte[syLen];
Buffer.BlockCopy(client.m_stream,allLen,syData,0,syLen);
client.m_stream = syData;
}
else//如果没数据了就初始化
{
client.m_stream = new byte[0];
break;
}
}
else
{
break;
}
}
//解析数据//等待接收数据 如果还有消息发来继续接收,如果没有就跳过
client.m_socket.BeginReceive(client.m_data,0,client.m_data.Length,SocketFlags.None, OnReceive,client);
}
else
{
m_clients.Remove(client);
//发送离线消息, 给其他在线用户,发送了你离线的消息了
YBNetManager.instance.AllSend(MsgId.S2C_LEVEL, client.m_player.ToByteArray());
//离线
Console.WriteLine(client.m_strIP + "离线");
}
}
//已弃用
//Json解析
public void testJson()
{
List<loginMessage> m_list = new List<loginMessage>();
for (int i = 0; i < 5; i++)
{
loginMessage user = new loginMessage();
user.strPassword = "pass" + i;
user.strUserName = "name" + i;
m_list.Add(user);
}
string json = JsonConvert.SerializeObject(m_list);
List<loginMessage> msg = JsonConvert.DeserializeObject<List<loginMessage>>(json);
}
//给所有的客户端发消息
public void AllSend(int id,byte[] body)
{
foreach (var item in m_clients)
{
Send(id,body,item);
}
}
//业务,各种功能;
//发数据如:聊天包,登录包等等...
public void Send(int id,byte[] boby,Client client)
{
//拼包
byte[] head = BitConverter.GetBytes(id);//包头,包的id;
byte[] len = BitConverter.GetBytes((ushort)(head.Length+boby.Length));//包的长度
//拼包
byte[] data = new byte[0];
data = data.Concat(len).ToArray();//长度
data = data.Concat(head).ToArray();//id的长度
data = data.Concat(boby).ToArray();//内容长度
//发数据
client.m_socket.BeginSend(data,0,data.Length,SocketFlags.None,OnSend,client);
}
private void OnSend(IAsyncResult ar)
{
Client client = ar.AsyncState as Client;
int nLen = client.m_socket.EndSend(ar);
Console.WriteLine("发送的数据长度"+nLen);
}
//public Player findPlayer(string strId)
//{
// num++;
// Console.WriteLine("攻击了"+num+"次");
// Player pReult = null;
// foreach (var item in m_clients)
// {
// if (item.m_player.StrId==strId)//找到被攻击的玩家修改血量;
// {
// item.m_player.Hp -= 10;
// pReult = item.m_player;
// break;
// }
// }
// return pReult;
//}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)