因此,在AS3中使用TCP,我试图将字符串写入服务器然后再写入客户端,但它似乎只能一次读取一个。这不好,因为我根据按下的键发送消息,并且客户端有一个需要根据按下的键进行的操作。由于一次可以按下多个键,显然它无法正常工作。
客户端示例:
if (keys[p1_jump_key])
{
p1_up = "down";
sock.writeUTF("p1_up_down");
sock.flush();
}
else
{
p1_up = "up";
sock.writeUTF("p1_up_up");
sock.flush();
}
if (keys[p1_crouch_key])
{
p1_down = "down";
sock.writeUTF("p1_down_down");
sock.flush();
}
else
{
p1_down = "up";
sock.writeUTF("p1_down_up");
sock.flush();
}
然后是服务器:
function socketDataHandler(event:ProgressEvent):void{
var socket:Socket = event.target as Socket;
var message:String = socket.readUTF();
for each (var socket:Socket in clientSockets)
{
socket.writeUTF(message);
socket.flush();
}}
最后,这是接收客户端(我有一个允许服务器区分两者的方法):
if(msg=="p1_down_down"){
p1_down="down";
}
if(msg=="p1_down_up"){
p1_down="up";
}
if(msg=="p1_up_down"){
p1_down="down";
}
if(msg=="p1_up_up"){
p1_down="up";
}
现在很多人已经看到了这个问题,因为当向下键启动时,它会发送消息" p1_down_up"。当up键启动时,它会发送消息" p1_up_up"。当两个消息都没有被按下时,两个消息都立即发送。我想,接收客户端只是获取其中一个信号,或者可能都没有。如何通过服务器写入和读取MULTIPLE信号?我尝试使用数组,但你显然无法写出来。谢谢。
答案 0 :(得分:1)
对于其他遇到此问题的人,就像我试图弄清楚如何实现这一点一样,我不得不说提供的其他解决方案效率极低,过于复杂且难以阅读。您可以简单地让服务器发送整个消息的长度以确定消息是否在多个数据包中,并确保您读取多个写入,而不是在消息末尾添加空字节并将数据包推送到数组中。正确的顺序。
这是一个有效的客户端接收功能。我将数据作为转换为ByteArrays的压缩对象发送。对象可以存储任何类型的数据,使其成为从服务器到客户端传输复杂信息的理想选择。
var messageBytes: ByteArray = new ByteArray;
var messageLength: int = 0;
var readBuffer = false;
function receiveTCP(e: ProgressEvent): void {
while (e.target.bytesAvailable >= 4) {//Loop to see if there is data in the socket that is available to read.
if (messageLength == 0) {
messageLength = e.target.readUnsignedInt();//read the first 4 bytes of data to get the size of the message and store it as our message length.
readBuffer = true;//set the readBuffer to true. While this is true, the function wont be reading any more data from the server until the current message is finished being read.
}
if (messageLength <= e.target.bytesAvailable) {//check to see if our message is finished being read.
if (readBuffer == true) {//Make sure another message isn't being read. Without this check, another incoming message from the server will overwrite the current one from being executed.
e.target.readBytes(messageBytes, 0, messageLength);//reads the byte array into our messageBytes ByteArray declared at the top.
messageBytes.uncompress();//decompresses our message
var message: Object = new Object();
message = messageBytes.readObject();//Writes our ByteArray into an object again.
receiveMessage(message);//send our message to another function for the data to be executed.
messageLength = 0;//reset our messageLength for the next message.
readBuffer = false;//reset our buffer so that the client can read the next message being received, or the next message in line.
} else {
receiveTCP(e);//if there is another message in wait and the previous one isn't finished reading, execute the same function with the same event data again. Eventually the buffer will open and the message will be read.
}
} else {
break;//If the message is split up into multiple packets, this will reset the loop to continue reading the message until all the packets are accounted for.
}
}
}
这将防止阻塞,允许您同时接收多条消息并将多个数据包中传递的消息放在一起。
不可否认,这需要一段时间才能弄明白。如果您需要服务器端代码来发送消息,请告诉我。
答案 1 :(得分:0)
TCP协议由双向字节流组成,因此不保留消息边界。因此,如果您经常发送消息,则最终可以从缓冲区中读取两条消息而不是一条消息。
因此,您发送的某些消息可能正在一起处理,这使接收端的比较测试失败。
要解决此问题,您可以在每封邮件的末尾附加分隔符。这样,您就可以知道您发送的每条消息的开始和结束位置,从而允许您单独拆分和处理它们。这也意味着在每次写入缓冲区后都不需要刷新。
例如,您可以使用空字节(\0
)作为分隔符。
if(keys[p1_jump_key])
{
p1_up = "down";
sock.writeUTF("p1_up_down\0");
}
...
sock.flush();
在接收端,我们修剪任何尾随分隔符,然后将消息拆分为较小的数据包。
编辑:修复您描述的问题会产生另一个问题:您的消息可能会被拆分为两个缓冲区读取。我已经编辑了我的代码以反映这个问题的解决方案,通过创建一个存储部分消息的临时变量,在以下读取中添加到消息的其他部分。
// First we check to see if there are any 'parts' of a message that we've stored temporarily from the last read. If so, prepend them to the message string, which must be its continuation
if(temp != "")
{
msg = temp + msg;
temp = "";
}
// Now we begin processing our packet
var splitPackets:Array = msg.split("\0");
var packets:Array = new Array();
// Deal with incomplete message reads
if(splitPackets[splitPackets.length - 1] != "")
{
// If the last item in our array isn't empty, it means out message stream ended in a partial message. Hence, we have to store this value temporarily, and append it on the next read of the stream
temp = splitPackets[splitPackets.length - 1];
}
// If the last item in our array is empty, it means our message stream ends in a full message
for(var i = 0; i < splitPackets.length - 1; i++)
{
packets[i] = splitPackets[i];
}
for(var i = 0; i < packets.length; i++)
{
if(packets[i] == "p1_down_down")
{
// Process each packet individually here
...
// If you have already processed the packet, move on to the next
continue;
}
// Processing code for other packets
...
}
希望这有帮助!