Я собираю дейтаграммы для связи UDP с подзаголовком, который я использую, чтобы указать тип отправляемых данных. Клиент работает на C #, сервер работает на Java, а подзаголовок представляет собой один Int32, то есть 4 байта данных.
Данные успешно поступают на сервер, и данные подзаголовка + интерпретируются правильно, но когда я отправляю ответ обратно клиенту, использование BitConverter.ToInt32 (подзаголовок, 0) приводит к 8-значному числу, которое не отображается к любому из моих ожидаемых целых чисел. Однако отправленные данные корректно отображаются при пропуске подзаголовка, что заставляет меня думать, что проблема связана только с процессом кодирования / декодирования подзаголовка.
У меня есть методы на обоих концах, которые могут вычистить подзаголовок из байтового массива, и которые пытаются сопоставить вычищенный подзаголовок с MsgType. Как я уже упоминал, на сервере все работает, как и ожидалось, поэтому я подозреваю, что проблема заключается в кодировании на сервере или в декодировании обратно на клиенте.
Я также пытался использовать MemoryStream и BinaryReader для преобразования в Int32, но с теми же результатами.
C # Клиент:
const SUBHEADER_SIZE = 4; // 4 bytes to an Int32
private void ReceiveUdp(IAsyncResult packet)
{
IPEndPoint remote = (IPEndPoint)Udp.Client.RemoteEndPoint;
byte[] received = Udp.EndReceive(packet, ref remote);
MsgType type = GetMsgType(received);
string msg;
switch (type)
{
case MsgType.POS:
case MsgType.STATE:
case MsgType.STATUS:
msg = Encoding.ASCII.GetString(ScrubSubheader(received));
if (msg.Equals("0"))
Disconnect();
break;
case MsgType.MSG: // Default to MSG
default:
msg = Encoding.ASCII.GetString(ScrubSubheader(received));
LocalConsole.Instance.Log("Received [" + type + "] " + msg + " from " + remote.Address + " on port " + remote.Port);
break;
}
}
public static byte[] ScrubSubheader(byte[] arr)
{
byte[] scrubbed = new byte[arr.Length - SUBHEADER_SIZE];
for (int i = 0; i < scrubbed.Length; i++)
scrubbed[i] = arr[i + SUBHEADER_SIZE];
return scrubbed;
}
public static MsgType GetMsgType(byte[] arr)
{
byte[] subheader = new byte[SUBHEADER_SIZE];
for (int i = 0; i < SUBHEADER_SIZE; i++)
subheader[i] = arr[i];
int iType = BitConverter.ToInt32(subheader, 0);
MsgType mtType;
// Also tried: "MemoryStream stream = new MemoryStream(subheader);
// int iType = new BinaryReader(stream).ReadInt32();"
LocalConsole.Instance.Log("iType is " + iType, true);
switch(iType)
{
case (int)MsgType.POS:
mtType = MsgType.POS;
break;
case (int)MsgType.STATE:
mtType = MsgType.STATE;
break;
case (int)MsgType.STATUS:
mtType = MsgType.STATUS;
break;
case (int)MsgType.MSG: // Default to MSG
default:
mtType = MsgType.MSG;
break;
}
return mtType;
}
Java-сервер:
public void run() {
try (DatagramSocket udpServSock = new DatagramSocket(_port)) {
DatagramPacket packet = null;
byte[] byteArr = new byte[HubrisServer.MAX_PACKET_SIZE];
while (true) {
packet = new DatagramPacket(byteArr, byteArr.length);
udpServSock.receive(packet);
InetAddress clientAdd = packet.getAddress();
int clientPort = packet.getPort();
MsgType type = getMsgType(packet.getData());
String msg = DataToString(scrubSubheader(packet.getData()), true);
MsgType sendType = HubrisServer.MsgType.STATUS;
msg = "0";
byte[] sendArr = assemblePacket(msg.getBytes(), sendType);
DatagramPacket sendPack = new DatagramPacket(sendArr, sendArr.length, clientAdd, clientPort);
Thread.sleep(1000);
udpServSock.send(sendPack);
}
} catch ... {
...
}
}
/**
* Assemble a packet with subheader and data
* @param arr
* @param type
* @return packet
*/
public static byte[] assemblePacket(byte[] arr, MsgType type) {
ByteBuffer buff = ByteBuffer.allocate(4);
buff.putInt(type.getValue());
byte[] subheader = buff.array();
byte[] packet = new byte[arr.length + subheader.length];
for(int i = 0; i < packet.length; i++) {
if(i >= subheader.length)
packet[i] = arr[i - subheader.length];
else
packet[i] = subheader[i];
}
return packet;
}
/**
* Scrub the subheader from a byte array and return the scrubbed array
* @param arr
* @return
*/
public static byte[] scrubSubheader(byte[] arr)
{
... similar to C# implementation
}
public static MsgType getMsgType(byte[] arr)
{
byte[] subArr = new byte[SUBHEADER_SIZE];
for (int i = 0; i < SUBHEADER_SIZE; i++)
subArr[i] = arr[i];
ByteBuffer buff = ByteBuffer.wrap(subArr);
int iType = buff.getInt();
MsgType mtType;
if(iType == MsgType.POS.getValue())
mtType = MsgType.POS;
else if (iType == MsgType.STATE.getValue())
mtType = MsgType.STATE;
else if (iType == MsgType.STATUS.getValue())
mtType = MsgType.STATUS;
else // Default to MSG
mtType = MsgType.MSG;
return mtType;
}