简体   繁体   English

通过 TCP 同时发送两个数据包时,一个丢失

[英]When sending two packets at once over TCP one is lost

I use Java as a server, and PHP as a client, so after connecting to the server, I do socket_set_nonblock (so that the flow does not stop when socket_read), then through while() I accept packages (socket_read), but the trouble is, if you send two packages at once, the second one disappears.我用Java作为服务端,PHP作为客户端,所以连接服务端后,我做socket_set_nonblock(这样socket_read时流不停止),然后通过while()我接受包(socket_read),但是麻烦也就是说,如果您一次发送两个包裹,第二个就会消失。

// socket class
public function __construct(int $port) {
    if(!($this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)))
        var_dump('Ошибка при создании сокета: ' . socket_strerror(socket_last_error()) . PHP_EOL);
    if (!@socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1))
        var_dump('Не могу установить опцию на сокете: ' . socket_strerror(socket_last_error()) . PHP_EOL);
    if(!@socket_bind($this->socket, '127.0.0.1', $port))
        var_dump('Не удалось привязать адрес: ' . socket_strerror(socket_last_error()) . PHP_EOL);
}

public function connect(string $address, int $port): bool {
        if(($result = @socket_connect($this->socket, $address, $port)))
            if(!socket_set_nonblock($this->socket))
                var_dump('Не могу установить опцию: [nonblock] на сокете: ' . socket_strerror(socket_last_error()) . PHP_EOL);
        return $result;
    }

public function readData(): string {
    return socket_read($this->socket, ClientConst::MTU_SIZE);
}

// main class
public function main() {
    while(true) {
        if(($rawPacket = $this->primarySocket->readData()) !== '') {
            //todo: 
        }
    }
}

TCP does not have messages. TCP 没有消息。 TCP sends a stream of bytes. TCP 发送一个 stream 字节。 There is no guarantee that one 'send' results in one 'receive' at the other end.不能保证一个“发送”会在另一端导致一个“接收”。 It could be that the receive call reads data from two sends;可能是接收调用从两个发送中读取数据; it could be that two receive calls each read only part of the data from one send.可能是两个接收调用,每个调用只读取一次发送的部分数据。

If you want message boundaries you need to provide them.如果您想要消息边界,则需要提供它们。 There are two common techniques: precede each message by a length, and read that many bytes;有两种常见的技术:在每条消息前面加上一个长度,然后读取那么多字节; or use a delimiter (such as \n) and read up to the delimiter.或使用分隔符(例如 \n)并读取到分隔符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM