标签:protobuf 异步通讯 数据缓冲
这是一个简单的c#异步通讯的例子(只有客户端哦)
C# 异步通讯
自定义数据头
protobuf
数据缓冲,,解包
代码伺候:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using ProtoBuf;
namespace ProtobufExample
{
class Program
{
static byte[] buffer = new byte[1024];
static int writeIndex = 0;
static int readIndex = 0;
private static Packet current;
private static TcpClient client;
private static NetworkStream networkStream;
static void Main(string[] args)
{
IPAddress address=new IPAddress(new byte[]{127,0,0,1});
Int32 port=8000;
client = new TcpClient();
client.BeginConnect(address,port,new AsyncCallback(ConnectCallback),client);
while (true)
{
if (networkStream != null)
{
write(client);
}
Thread.Sleep(100);
}
}
public static void ConnectCallback(IAsyncResult result) {
TcpClient client=(TcpClient)result.AsyncState;
client.EndConnect(result);
networkStream = client.GetStream();
read(client);
}
private static void write(TcpClient client)
{
//发送请求游戏服列表协议
Packet packet = new Packet();
packet.Header.Pid = 10001;
byte[] data=new byte[PacketHeader.header_size];
packet.Header.serialize(data,0);
networkStream.BeginWrite(data, 0, data.Length, new AsyncCallback(WriteCallback), networkStream);
}
public static void WriteCallback(IAsyncResult result) {
NetworkStream networkStream = (NetworkStream)result.AsyncState;
networkStream.EndWrite(result);
Console.WriteLine("数据包已发送");
}
public static void read(TcpClient client) {
NetworkStream networkStream=client.GetStream();
networkStream.BeginRead(buffer, writeIndex, buffer.Length - writeIndex, new AsyncCallback(ReadCallback), networkStream);
}
public static void ReadCallback(IAsyncResult result) {
NetworkStream networkStream = (NetworkStream)result.AsyncState;
int readbytes=networkStream.EndRead(result);
writeIndex += readbytes;
Console.WriteLine("读取字节数:"+readbytes);
Packet packet = null;
while ((packet = readPacket())!=null) {
Console.WriteLine("收到协议:" + packet.Header.Pid);
MemoryStream ms = new MemoryStream(packet.Content);
ServerListResp resp=Serializer.Deserialize<ServerListResp>(ms);
Console.WriteLine("服务器列表:" + resp.servers.Count);
}
networkStream.BeginRead(buffer, writeIndex, buffer.Length - writeIndex, new AsyncCallback(ReadCallback), networkStream);
}
public static Packet readPacket()
{
if (PacketHeader.header_size > writeIndex - readIndex)
{
return null;
}
if (current == null)
{
current = new Packet();
}
Packet temp = current;
temp.Header.deserialize(buffer, readIndex);
readIndex += PacketHeader.header_size;
if (temp.Header.BodyLength > writeIndex - readIndex)
{
return null;
}
byte[] data = new byte[temp.Header.BodyLength];
Array.Copy(buffer,readIndex,data,0,temp.Header.BodyLength);
temp.Content = data;
readIndex += temp.Header.BodyLength;
discardReadBytes();
return temp;
}
private static void discardReadBytes() {
if (readIndex == writeIndex) {
writeIndex =0;
readIndex = writeIndex;
}
else
{
int remaining = writeIndex - readIndex;
byte[] temp = new byte[remaining];
Array.Copy(buffer, readIndex, temp, 0, remaining);
writeIndex = remaining;
readIndex = 0;
Array.Copy(temp,buffer, remaining);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProtobufExample
{
class PacketHeader
{
public static int header_size = 6;
private int pid;
private int code;
private int bodyLength;
public void deserialize(byte[] src,int offset) {
this.code = src[offset] <<8|src[offset+1];
this.pid = src[offset+2] << 8 | src[offset + 3];
this.bodyLength = src[offset+4] << 8 | src[offset + 5];
}
public void serialize(byte[] dist,int offset) {
dist[offset]=(byte)(this.code>>8&0xff);
dist[offset+1] = (byte)(this.code & 0xff);
dist[offset + 2] = (byte)(this.pid >> 8 & 0xff);
dist[offset + 3] = (byte)(this.pid & 0xff);
dist[offset + 4] = (byte)(this.bodyLength >> 8 & 0xff);
dist[offset + 5] = (byte)(this.bodyLength & 0xff);
}
public int BodyLength
{
get{return bodyLength;}
set{this.bodyLength=value;}
}
public int Pid
{
get { return pid; }
set { this.pid = value; }
}
}
class Packet
{
private PacketHeader header;
private byte[] content;
public PacketHeader Header
{
get
{
if(header==null)
{
header=new PacketHeader();
}
return header;
}
set
{
this.header=value;
}
}
public byte[] Content
{
get
{
return content;
}
set
{
this.content = value;
}
}
}
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;
namespace ProtobufExample
{
[ProtoContract]
class ServerListResp
{
[ProtoMember(1)]
public List<Server> servers { get; set; }
}
[ProtoContract]
class Server
{
[ProtoMember(1)]
public Int32 serverId {get;set;}
[ProtoMember(2)]
public string serverName { get; set; }
[ProtoMember(3)]
public Int32 serverStatus { get; set; }
[ProtoMember(4)]
public Int32 serverLabel { get; set; }
}
}
标签:protobuf 异步通讯 数据缓冲