私が作成している Unity3D ゲーム用の単純な UDP ソケット サーバーを作成しようとしていますが、ほとんど動作しています。メッセージを送信してメッセージを読むことができます。しかし、メッセージをクライアントに送り返そうとすると (現時点ではテスト目的で)、BufferOverFlowException が発生します。
データを返送する前に、groovy.json.JsonBuilder を使用してデータを json に変換しています。データの構造は非常に単純です。
[データ:「ハローワールド」]
しかし、何らかの理由で JsonBuilder はそれを次のように構築しています
{
"data": "Hello World\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\..."
}
\u0000 がしばらく続きます。1024 バイトの長さの ByteBuffer がオーバーフローするのに十分な長さです。
これは、データをクライアントに送り返すクラスです。
import groovy.json.JsonBuilder
import groovy.transform.CompileStatic
import groovyx.gpars.actor.DynamicDispatchActor
import java.nio.ByteBuffer
import java.nio.channels.DatagramChannel
@CompileStatic
class SenderActor extends DynamicDispatchActor{
//takes message of type [data: Object, receiver: SocketAddress]
void onMessage(Map message){
println(message.data) //prints "Hello World"
def json = new JsonBuilder([data: message.data]).toString()
println("Sending: $json") //prints '{"data": "Hello World\u0000\u0000..."}'
def channel = DatagramChannel.open()
channel.connect(message.receiver as SocketAddress)
def buffer = ByteBuffer.allocate(1024)
buffer.clear()
buffer.put(json.getBytes())
buffer.flip()
channel.send(buffer, message.receiver as SocketAddress)
}
}
そして、これは私が得るスタックトレースです:
An exception occurred in the Actor thread Actor Thread 2
java.nio.BufferOverflowException
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:189)
at java.nio.ByteBuffer.put(ByteBuffer.java:859)
at Croquet.Actors.SenderActor.onMessage(SenderActor.groovy:28)
at Croquet.Actors.SenderActor$onMessage.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at Croquet.Actors.ProcessorActor$onMessage.call(Unknown Source)
at groovyx.gpars.actor.impl.DDAClosure$_createDDAClosure_closure1.doCall(DDAClosure.groovy:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:439)
at groovyx.gpars.actor.AbstractLoopingActor.runEnhancedWithoutRepliesOnMessages(AbstractLoopingActor.java:293)
at groovyx.gpars.actor.AbstractLoopingActor.access$400(AbstractLoopingActor.java:30)
at groovyx.gpars.actor.AbstractLoopingActor$1.handleMessage(AbstractLoopingActor.java:93)
at groovyx.gpars.util.AsyncMessagingCore.run(AsyncMessagingCore.java:132)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
問題のデータは UTF-8 でエンコードされています。
これは、サーバーへのデータ送信を担当するクライアント コードです (C# で記述)。
void sendTestMessage(UdpClient udpClient, UdpState udpState){
byte[] data = Encoding.UTF8.GetBytes("Hello World");
udpClient.BeginSend(
data,
data.Length,
udpState.e, //IPEndPoint
result =>{
messageSent = true;
Debug.Log(string.Format("Message '{1}' Sent to {0}", udpState.e, Encoding.UTF8.GetString(data)));
udpClient.EndSend(result);
},
udpState);
}