服务器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using Player;
namespace NBkalasi
{
internal class Client
{
public Socket socket;//定义个套接字
public string ipads;//IP地址
public byte[] data = new byte[1024];//数据的容量
public byte[] stream = new byte[0];//流
// public Player player;
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NBkalasi
{
internal class NetManager : Singleton<NetManager>
{
Socket socket;
//存所有客户端的集合
public List<Client> clientlist = new List<Client>();
public void Init()
{
//socket 赋值
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//给socket进行绑定
socket.Bind(new IPEndPoint(IPAddress.Any, 33333));//33333为你的端口号
//可以监听的上限为 10个
socket.Listen(10);
//开始接受客户端发送来的链接 1 当有客户端发送链接请求就调用函数
socket.BeginAccept(Linkq, null);
Console.WriteLine("启动服务器");
}
//客户端链接 调用
private void Linkq(IAsyncResult ar)
{
Client client = new Client();
//异步需要把ar结束后 赋给socket
client.socket = socket.EndAccept(ar);
//把ar传过来的ip和端口 接一下
IPEndPoint ipend= client.socket.RemoteEndPoint as IPEndPoint;
//拼接客户端的ip+端口
client.ipads = ipend.Address+":"+ipend.Port;
//输出一下 添加到集合
Console.WriteLine(client.ipads+"连接了");
clientlist.Add(client);
//这个客户端开始接受数据 1.byte[] 数组,2.从第0位开始接受3.数组总长度4.传输的协议为none 5.接受数据的回调函数 6.自己
client.socket.BeginReceive(client.data,0,client.data.Length,SocketFlags.None,OnReceive,client);
//再次接收链接
socket.BeginAccept(Linkq, null);
}
private void OnReceive(IAsyncResult ar)
{
try
{
//服务器获取已经链接的客户端
Client client = ar.AsyncState as Client;
//服务器获取已经链接的客户端的数据长度
int len = client.socket.EndReceive(ar);
//判读是否有数据
if (len>0)
{
//有数据的话 建立一个缓存全部数据的容器
byte[] Allbyte = new byte[len];
//把该客户端的缓存数据复制到容器里,把数组的第0位 copy 到 allbyte 的第0位开始 ,copy的长度
Buffer.BlockCopy(client.data,0,Allbyte,0,Allbyte.Length);
// 把缓存好的数据进行拼接拼接给最后的实际数据 把allbyte 拼接到流里
client.stream = client.stream.Concat(Allbyte).ToArray();
// 长度(包头加包体 2字节) +包头(id int 4字节) + 包体(数据)==包
while (client.stream.Length>=2)
{
//获取包头和包体的长度(api的意思是从数据的第0位开始,获取Ushout类型的数据 获取到就结束)
ushort onelen =BitConverter.ToUInt16(client.stream,0);
//获取包里面数据的 总长度
int alllen = 2 + onelen;
//判断是否有一个以上的包
if (client.stream.Length >= alllen)
{
//建立一个只存包头+包体的缓存数据的容器
byte[] onedata = new byte[onelen];
//从该客户端的数据里,去除包里长度后(长度是2字节,也就是从包头开始Copy数据),
Buffer.BlockCopy(client.stream, 2, onedata, 0,onedata.Length);
//从上面的容器里 第0位开始获取id;
int id = BitConverter.ToInt32(onedata,0);
// Console.WriteLine(id);
//从上面容器 除去id(包头)的字节数 创建包体的容器
byte[] onedata2 = new byte[onedata.Length-4];
//从上面包头加包体的容器里除去包头 copy 包体到上面包体的容器里
Buffer.BlockCopy(onedata, 4, onedata2, 0, onedata2.Length);
//消息中心发送(id消息号,包体作为数据,传过来的客户端)
MessageCenter.Ins.OnDisPatch(id, onedata2,client);
//看看数据里是否有剩余的包
int sylen = client.stream.Length - alllen;
//如果有
if (sylen>0)
{
//创建个存储的容器
byte[] sybyte = new byte[sylen];
//把剩余的数据copy 到剩余包的容器中
Buffer.BlockCopy(client.stream, alllen, sybyte, 0,sybyte.Length);
//重新给数据赋值
client.stream = sybyte;
}
else
{
//如果没有剩余的包 给他变成空的数组
client.stream = new byte[0];
break;
}
}
else
{
break;
}
}
//只要客户端传数据 都会重新调用方法
client.socket.BeginReceive(client.data, 0, client.data.Length, SocketFlags.None, OnReceive, client);
}
else
{
//如果没有数据 都关闭
client.socket.Shutdown (SocketShutdown.Both);
client.socket.Close();
clientlist.Remove(client);
Console.WriteLine(client.ipads+"滚啦");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void Send(int id,byte[] body,Client client)
{
byte[] head = BitConverter.GetBytes(id);
byte[] upbody = BitConverter.GetBytes((ushort)(head.Length + body.Length));
byte[] allbody = new byte[0];
allbody = allbody.Concat(upbody).ToArray();
allbody = allbody.Concat(head).ToArray();
allbody = allbody.Concat(body).ToArray();
client.socket.BeginSend(allbody, 0, allbody.Length, SocketFlags.None, OnSend, client);
}
private void OnSend(IAsyncResult ar)
{
Client client = (Client)ar.AsyncState;
int len = client.socket.EndSend(ar);
Console.WriteLine("发送长度"+len);
}
public void OnAllSend(int id,byte[] body)
{
for (int i = 0; i < clientlist.Count; i++)
{
Send(id, body, clientlist[i]);
}
}
}
}
客户端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Linq;
using System;
public class NetManager : Singleton<NetManager>
{
Socket socket;
public byte[] data = new byte[1024];
public byte[] stream = new byte[0];
Queue<byte[]> queue = new Queue<byte[]>();
public void Init()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect("127.0.0.1",33333,OnConnect, null);
}
private void OnConnect(IAsyncResult ar)
{
socket.EndConnect(ar);
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
}
private void OnReceive(IAsyncResult ar)
{
try
{
int len = socket.EndReceive(ar);
if (len > 0)
{
byte[] alldata = new byte[len];
Buffer.BlockCopy(data, 0, alldata, 0, len);
stream = stream.Concat(alldata).ToArray();
while (stream.Length >= 2)
{
ushort baolen = BitConverter.ToUInt16(stream, 0);
int alllen = 2 + baolen;
if (stream.Length >= alllen)
{
byte[] idbody = new byte[baolen];
Buffer.BlockCopy(stream, 2, idbody, 0, baolen);
queue.Enqueue(idbody);
int sylen = stream.Length - alllen;
if (sylen > 0)
{
byte[] sydata = new byte[sylen];
Buffer.BlockCopy(stream, alllen, sydata, 0, sylen);
stream = sydata;
}
else
{
stream = new byte[0];
break;
}
}
else
{
break;
}
}
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
}
else
{
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void Send(int id, byte[] body)
{
byte[] head = BitConverter.GetBytes(id);
byte[] len = BitConverter.GetBytes((ushort)(head.Length + body.Length));
byte[] alldata = new byte[0];
alldata = alldata.Concat(len).ToArray();
alldata = alldata.Concat(head).ToArray();
alldata = alldata.Concat(body).ToArray();
if (socket.Connected)
{
socket.BeginSend(alldata, 0, alldata.Length, SocketFlags.None, OnSend, null);
}
}
private void OnSend(IAsyncResult ar)
{
int len = socket.EndSend(ar);
Console.WriteLine("发送的长度为" + len);
}
public void Close()
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
public void UpData()
{
if (queue.Count>0)
{
byte[] idbody = queue.Dequeue();
int id = BitConverter.ToInt32(idbody, 0);
byte[] body = new byte[idbody.Length - 4];
Buffer.BlockCopy(idbody, 4, body, 0, idbody.Length - 4);
MessageCenter.Ins.OnDisPatch(id, body);
}
}
}