本框架一共分是三个部分,运用TCP网络连接协议:
1、客户端(winform);2、服务端(winform);3、socket功能类库模块(其他项目也可以引用),socket类库模块功能齐全,只需调用其中方法即可,复用性较强,代码注释详细,实现了心跳,解决了粘包问题,异步发送接收数据,等等,bin目录下右运行日志方便查找程序运行状况,可以有多个客户端发送消息,服务端可以广播消息也可以定向发送给某个客户端,
首先,Socket(套接字)是一个网络编程概念,描述了一个通信端点(Endpoint),用于建立网络连接(Connection)并传输数据。在强联网通信中,Socket连接,也称为强连接或长连接,是实现网络通信的关键。这种连接具有实时性和长连接的特点,使得数据可以在网络中进行持续、稳定的传输。
其次,关于分包和粘包,这是TCP协议下Socket通信内部的一种优化机制。粘包现象是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。分包则是指接收方在出现粘包现象时需要进行的处理,以确保数据的正确接收。这些现象在强联网通信中可能会出现,但并非强联网通信的必然特征。
服务器框架
internal class NetManager:Singleton<NetManager>
{
Socket socket;
public List<Client>listclient=new List<Client>();
public void Init()
{
socket=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 12345));
socket.Listen(1000);
socket.BeginAccept(Onaccept,null);
}
///进行连接,共三次挥手连接
private void Onaccept(IAsyncResult ar)
{
Socket client= socket.EndAccept(ar);
Client cli = new Client();
cli.socket= client;
listclient.Add(cli);
IPEndPoint ip = cli.socket.RemoteEndPoint as IPEndPoint;
Console.WriteLine(ip.Address+":"+ip.Port+"已连接");
cli.socket.BeginReceive(cli.data,0,cli.data.Length,SocketFlags.None,OnReceive,cli);
socket.BeginAccept(Onaccept, null);
}
//接收消息后进行分包处理
private void OnReceive(IAsyncResult ar)
{
Client cli=ar.AsyncState as Client;
int len=cli.socket.EndReceive(ar);
if(len<=0)
{
cli.socket.Shutdown(SocketShutdown.Both);
cli.socket.Close();
listclient.Remove(cli);
foreach (var item in listclient)
{
Send(item, MsgID.S2C_Leave,cli.my.ToByteArray());
}
return;
}
byte[] data = cli.data.Take(len).ToArray();
cli.stream=cli.stream.Concat(data).ToArray();
while(cli.stream.Length>=2)
{
ushort onelen=BitConverter.ToUInt16(cli.stream,0);
if (cli.stream.Length>=2+onelen)
{
int id = BitConverter.ToInt32(cli.stream, 2);
byte[] body = cli.stream.Skip(6).Take(onelen - 4).ToArray();
MessManager<Message>.Ins.Brodcast(id, new Message(cli, body));
cli.stream = cli.stream.Skip(onelen + 2).ToArray();
}
else
{
break;
}
}
cli.socket.BeginReceive(cli.data, 0, cli.data.Length, SocketFlags.None, OnReceive, cli);
}
///向客户端发送消息
public void Send(Client cli,int id, byte[] body)
{
byte[] len = BitConverter.GetBytes((ushort)(4 + body.Length));
byte[] head = BitConverter.GetBytes(id);
byte[] data=len.Concat(head).Concat(body).ToArray();
cli.socket.Send(data);
}
}
客户端框架
public class NetManager : Singleton<NetManager>
{
Socket socket;
byte[] data=new byte[1024];
byte[]stream= new byte[0];
Queue<byte[]>que=new Queue<byte[]>();
public void Init()
{
socket=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect("127.0.0.1",12345, OnAccept, null);
}
private void OnAccept(IAsyncResult ar)
{
socket.EndConnect(ar);
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
}
private void OnReceive(IAsyncResult ar)
{
int len=socket.EndReceive(ar);
if(len<=0)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
return;
}
byte[] buffer=data.Take(len).ToArray();
stream=stream.Concat(buffer).ToArray();
while(stream.Length>=2)
{
ushort onelen=BitConverter.ToUInt16(stream,0);
if(stream.Length>=2+onelen)
{
que.Enqueue(stream.Skip(2).Take(onelen).ToArray());
stream=stream.Skip(onelen+2).ToArray();
}
else
{
break;
}
}
socket.BeginReceive(data,0,data.Length, SocketFlags.None,OnReceive, null);
}
public void Update()
{
while(que.Count>0)
{
byte[] buffer= que.Dequeue();
int id=BitConverter.ToInt32(buffer,0);
byte[] body=buffer.Skip(4).Take(buffer.Length-4).ToArray();
MessManager<byte[]>.Ins.Broadcast(id, body);
}
}
public void Send(int id, byte[] body)
{
byte[] len = BitConverter.GetBytes((ushort)(4 + body.Length));
byte[] head = BitConverter.GetBytes(id);
byte[] buffer= len.Concat(head).Concat(body).ToArray();
socket.Send(buffer);
}
public void Close()
{
socket.Close();
socket.Shutdown(SocketShutdown.Both);
}
}
总的来说,Socket网络框架是实现强联网通信的基础,而分包和粘包则是网络通信中可能出现的一种现象,需要通过特定的处理方式来解决。虽然这些概念与强联网通信有关,但并不能直接等同于强联网通信本身。强联网通信更侧重于使用Socket等网络技术实现稳定、实时的网络连接和数据传输。