TcpListener 服务器 - 处理数据
TcpListener server - handle data
我已经开始了我的第一个 Socket 项目,我想知道我应该如何通过
读取和发送数据
服务器 <=> 客户端
我应该进行序列化 class,使用最大缓冲区大小并且不要让我的脑海中浮现出字节,或者使其全部同步,仅在需要时读取和发送字节。
序列化(部分代码):
// TcpDLL
[Serializable]
public class SerializedData {
public string Message { get; set; }
public DataTypes Type { get; set; }
public object Data { get; set; }
}
private void ReadStream() {
// ...
stream.BeginRead(buffer, 0, MAX_BUFFER_SIZE, new AsyncCallback(ReadAsync), stream);
// ...
}
private void ReadAsync() {
// ...
var dataInfo = (SerializedData)BinaryFormatter.Deserialize(new MemoryStream(buffer));
if (dataInfo.Type == DataTypes.Register) {
var data = (RegisterClass)dataInfo.Data;
}
// ...
}
或者让它完全同步:
private void ReadStream() {
int bytes = ReadBytesInt(4); // read size of string Message
string Message = ReadBytesStr(bytes);
var Type = (DataTypes)ReadBytesInt(4);
bytes = ReadBytesInt(4); // read size of Data
if (Type == DataTypes.Register) {
RegisterClass.ReadStream();
}
// ...
}
private void RegisterClass.ReadStream() {
int id = ReadBytesInt(4);
// Read rest of data
}
或者合并?像这样:
private void ReadStream() {
int bytes = ReadBytesInt(4); // read size of SerializedData object
var dataInfo = (SerializedData)ReadBytesAndDeserialize(bytes);
// ...
}
最好的方法是什么?为什么?一次读取更多数据好还是尽可能小好?
TCP 是一种流式传输协议,因此如果您想发送多条消息,您应该提供某种方式来向另一端指示消息何时完成。
这通常是通过首先发送消息的大小,然后是消息本身来完成的。所以是的,你现在所做的事情的组合就是人们通常做的事情。
但是您应该记住,数据可能不会一次性全部接收 - TCP 仅确保数据按发送顺序和后续顺序接收。换句话说:
- 继续阅读,直到阅读完传入消息的大小
- 在传入消息的一侧创建缓冲区
- 继续阅读直到缓冲区填满
读取的数据量并不真正相关,传入数据存储在套接字级别,您的读取操作只是清空本地缓冲区。当然不建议逐字节读取。
大小很重要,没有必要为每个单独的字段指定大小。但是不用担心额外的几个字节。
我已经开始了我的第一个 Socket 项目,我想知道我应该如何通过
读取和发送数据
服务器 <=> 客户端
我应该进行序列化 class,使用最大缓冲区大小并且不要让我的脑海中浮现出字节,或者使其全部同步,仅在需要时读取和发送字节。
序列化(部分代码):
// TcpDLL
[Serializable]
public class SerializedData {
public string Message { get; set; }
public DataTypes Type { get; set; }
public object Data { get; set; }
}
private void ReadStream() {
// ...
stream.BeginRead(buffer, 0, MAX_BUFFER_SIZE, new AsyncCallback(ReadAsync), stream);
// ...
}
private void ReadAsync() {
// ...
var dataInfo = (SerializedData)BinaryFormatter.Deserialize(new MemoryStream(buffer));
if (dataInfo.Type == DataTypes.Register) {
var data = (RegisterClass)dataInfo.Data;
}
// ...
}
或者让它完全同步:
private void ReadStream() {
int bytes = ReadBytesInt(4); // read size of string Message
string Message = ReadBytesStr(bytes);
var Type = (DataTypes)ReadBytesInt(4);
bytes = ReadBytesInt(4); // read size of Data
if (Type == DataTypes.Register) {
RegisterClass.ReadStream();
}
// ...
}
private void RegisterClass.ReadStream() {
int id = ReadBytesInt(4);
// Read rest of data
}
或者合并?像这样:
private void ReadStream() {
int bytes = ReadBytesInt(4); // read size of SerializedData object
var dataInfo = (SerializedData)ReadBytesAndDeserialize(bytes);
// ...
}
最好的方法是什么?为什么?一次读取更多数据好还是尽可能小好?
TCP 是一种流式传输协议,因此如果您想发送多条消息,您应该提供某种方式来向另一端指示消息何时完成。
这通常是通过首先发送消息的大小,然后是消息本身来完成的。所以是的,你现在所做的事情的组合就是人们通常做的事情。
但是您应该记住,数据可能不会一次性全部接收 - TCP 仅确保数据按发送顺序和后续顺序接收。换句话说:
- 继续阅读,直到阅读完传入消息的大小
- 在传入消息的一侧创建缓冲区
- 继续阅读直到缓冲区填满
读取的数据量并不真正相关,传入数据存储在套接字级别,您的读取操作只是清空本地缓冲区。当然不建议逐字节读取。
大小很重要,没有必要为每个单独的字段指定大小。但是不用担心额外的几个字节。