我有一台服务器,它将通过一个连接将多个文件传输到客户端。来自服务器的数据包采用以下格式: unique_packet_id | FILE_CONTENT
我有onDataReceived函数,我需要像这样工作:
public class TRACK_ID {
public string id;
public string unknown_identifier;
}
List<TRACK_ID> TRACKER = new List<TRACK_ID>();
public void OnDataReceived(IAsyncResult asyn)
{
try
{
log("OnDataReceived");
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
// .. read the data into data_chunk
// if seperator found, that means we got an first chunk with the id
if (data_chunk.Contains("|") == true)
{
// extract unique_packet_id from the data
// bind unique_packet_id to an some kind of identifier? how!!??
TRACK_ID new_track = new TRACK_ID();
new_track.id = unique_packet_id;
new_track.unknown_identifier = X;
TRACKER.add(new_track);
} else {
// no seperator found - we're getting the rest of the data
// determinate the unique_packet_id of the incoming data so we can distinguish data/files
string current_packet_id = "";
for(int i=0; i<TRACKER.count; i++){
if(TRACKER[i].unknown_identifier == X){
current_packet_id = TRACKER[i].id; // we found our packet id!
break;
}
}
// now we got our packet_id and know where to store the buffer
}
WaitForData..
}
}
我需要一个变量X,它允许我跟踪存储每个传入缓冲区的位置
如果我关闭每个文件的连接,我可以将unique_packet_id绑定到socket_id(socket_id将是X),但由于我使用相同的连接,socket_id总是保持不变所以我必须为此X变量使用其他东西。
我能想到的其他解决方案是在每个数据块中发送unique_packet_id。但这似乎不是最好的方法。然后我必须将文件缓冲区拆分为块并将id附加到每个块。还有其他方法可以做到这一点吗?谢谢!
答案 0 :(得分:1)
您没有说明您是使用流套接字还是数据报套接字。
如果您正在使用数据报套接字(例如,您正在使用UDP / IP),那么您将始终一次性收到整个数据包,因此您可以识别数据,因为它与unique_packet_id
一致在当前数据包开头的|
之前找到。
如果您正在使用流套接字(例如,您使用的是TCP / IP),那么我认为您遇到了问题。您的数据包格式没有分隔或转义,那么您如何知道一个数据包的结束位置以及下一个数据包的开始?
如果您使用的是流套接字,则需要使用例如以下数据包格式:
接收方可以找到数据包的末尾,因为它知道有多少字节将成为有效载荷的一部分。
您还需要做好准备,以便获得一小块小包。例如,您的回调函数可能会使用部分唯一数据包ID调用一次,再次使用其余的标头和部分有效负载调用,并再次使用剩余的有效负载并将完整的后续数据包添加到最后。或者,您可以在一次调用回调函数时获得三个完整数据包和部分四分之一。
您提到的另一种可能的解决方案,即在每个数据块中发送unique_packet_id是不可能的,因为发送方不知道数据在传送到接收方时如何被分块。