用不同语言的套接字编码谜题


Encoding puzzles with sockets in different languages

我用PHP编写了以下代码,负责服务器套接字,特别是通过向某些套接字写入消息:

header('Content-Type: text/html; charset=utf-8');
const PAYLOAD_LENGTH_16 = 126;
const PAYLOAD_LENGTH_63 = 127;
const OPCODE_CONTINUATION  = 0;
for ($i = 0; $i < $frameCount; $i++) {
    // fetch fin, opcode and buffer length for frame
    $fin = $i != $maxFrame ? 0 : self::FIN;
    $opcode = $i != 0 ? self::OPCODE_CONTINUATION : $opcode;
    $bufferLength = $i != $maxFrame ? $bufferSize : $lastFrameBufferLength;
    // set payload length variables for frame
    if ($bufferLength <= 125) {
        $payloadLength = $bufferLength;
        $payloadLengthExtended = '';
        $payloadLengthExtendedLength = 0;
    }
    elseif($bufferLength <= 65535) {
        $payloadLength = self::PAYLOAD_LENGTH_16;
        $payloadLengthExtended = pack('n', $bufferLength);
        $payloadLengthExtendedLength = 2;
    } else {
        $payloadLength = self::PAYLOAD_LENGTH_63;
        $payloadLengthExtended = pack('xxxxN', $bufferLength); // pack 32 bit int, should really be 64 bit int
        $payloadLengthExtendedLength = 8;
    }
    // set frame bytes
    $buffer = pack('n', (($fin | $opcode) << 8) | $payloadLength).$payloadLengthExtended.substr($message, $i * $bufferSize, $bufferLength);

下面是Objective-C中负责从套接字服务器接收这些消息的代码:

NSInteger len = 0;
        uint8_t buffer[4096];
        while ([inputStream hasBytesAvailable]) {
            len = [inputStream read:buffer maxLength:sizeof(buffer)];
            if (len > 0) {
                [self.data appendBytes:buffer length:len];
                [self.log insertText:[NSString stringWithFormat:@"Log: Received a message from server:'n'n"]];
                NSLog(@"Received a message from server...");
            }
        }

当接收到所有字节时,我运行以下命令将数据转换为文件:

[self.data writeToFile:@"dataComes.txt" options:NSDataWritingAtomic error:nil]

问题

我们将为objective-c发送一个JSON格式的大文件,他将收到该信息,并生成一个名为dataComes.txt的文件,我可以正常看到JSON文件,但除了一些奇怪的字符,如:

~ or ~Â or â-Û

这些奇怪的字符总是出现在Objective-C接收到的每个消息块的开头(是的,套接字服务器和TCP将大型消息划分为消息块)。

这个问题的原因是什么?它如何解决这个问题?

解决方案1:过滤

我可以过滤掉可能出现的不需要的字符,但它也会过滤掉一些带有重音的单词:

NSCharacterSet *notAllowedChars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}:,'"] invertedSet];
NSString *resultString = [[total componentsSeparatedByCharactersInSet:notAllowedChars] componentsJoinedByString:@" "];

解决方案2:停止使用插座

我尝试了很多方法将数据发送到我的应用程序,唯一有效的方法是单独发送数据(一个JSON的循环),但为了工作,我不得不使用sleep(1)让我的代码(PHP)休眠(我认为这不好),因为如果不这样做,Objective-C就会识别出这些数据是一个单独的包。

在这种情况下,或者我的代码有问题,或者objective-c中套接字的编程做得不太好,并且存在不一致(bug)。我通过网络服务器的正常请求来处理我的连接(我认为这不是一个好主意,因为我必须在5分钟的时间间隔内每3秒进行一次)。

解决方案3:过滤+UNICODE

在服务器端,我可以过滤所有特殊字符,并为其创建一个特定的组合,例如:

Hello é worldHello /e001/ world

在我的应用程序中,我可以过滤这种组合并更改为真实格式。。。。