perl - Perl套接字编程发送方法

标签 perl sockets

我现在正在为简单的通讯进行套接字编程。

我注意到该服务器不是我创建的服务器,并且可以正常工作(考虑到实验性客户端)

在我的代码中,recv可以正常工作,但是send不起作用。我的代码有什么问题吗?

my $socket = new IO::Socket::INET (
    #PeerHost => '127.0.0.1',
    PeerHost => '192.168.0.100',
    PeerPort => '8472',
    Proto => 'tcp',
);
die "cannot connect to the server $!\n" unless $socket;
print "connected to the server\n";

while (1) {
    my $response = "";
    $socket->recv($response, 1024);
    if ($response) {
        my @test = split(//,$response);
        my ($length,$data) = unpack("N A*",$response);
        %json = json_decode($data,$length);

        switch ($json{'type'}) {
            case 1 { print "Game Start\n";}
            #case 2 { my $tmp = &my_turn(%json);} #my_turn func is return  "{'type': 0, 'point': [5, 4]}", but fail!
            #case 2 { $socket->send("{'type': 0, 'point': [5, 4]}");} # fail!
            case 2 { print $socket "{'type': 0, 'point': [5, 4]}"; print "ok\n";} # print is executed. However, the server does not receive packets
            #case 2 { $socket->send("{'type': 0, 'point': [5, 4]}");} #fail...
            case 3 { print "ACCEPT\n";}
            case 5 { print "NOPOINT\n";}
            case 6 { print "GAMEOVER\n";}
            case 7 { print "ERROR\n";}
            else {print "ERROR type : $json{'type'}\n"}
        }
    }
}

服务器工作正常。我检查了服务器提供的示例源(Python代码)。我想念什么?

最佳答案

  • 您不能假定recv(或read)将返回整个响应。您需要反复调用它。
  • 您不能假设recv(或read)只是响应。您需要限制缓冲区读取的大小多余。
  • decode_json返回一个引用(不是您可以分配给哈希的键/值对的列表)。
  • 您可能还必须处理JSON字符串的编码。下面的示例假定使用UTF-8编码。
  • 对服务器的JSON响应(原始代码中的case 2)也需要包含长度。

  • 应改用以下代码:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    use JSON;
    use IO::Socket;
    
    my $socket = IO::Socket::INET->new(
        PeerHost => '127.0.0.1',
        PeerPort => '22',
        Proto    => 'tcp',
    ) or
        die "cannot connect to the server $!\n";
    
    print "connected to the server\n";
    
    sub read_bytes($$) {
        my($socket, $length) = @_;
        my $result = '';
        print "ATTEMPT TO READ ${length}\n";
        while ($length > 0) {
            my $received = $socket->read($result, $length, length($result));
            die "socket error: $!\n" unless defined($received);
            die "unexpected EOF\n"   unless $received;
            $length -= $received;
        }
    
        print "READ '${result}'\n";
        return($result);
    }
    
    while (1) {
        my $length = unpack("N", read_bytes($socket, 4));
        my $json   = read_bytes($socket, $length);
        my $data   = JSON->new->utf8->decode($json);
    
        print $data->{type}, "\n";
    
        if ($data->{type} == 2) {
            my $response = {
                type  => 0,
                point => [5, 4],
            };
            my $resp_json = JSON->new->utf8->encode($response);
            print "JSON:   ${resp_json}\n";
    
            my $packet = pack('NA*', length($resp_json), $resp_json);
            print "PACKET: ", unpack('H*', $packet), "\n";
    
            $socket->write($packet);
        }
    }
    

    由于我无权访问您的服务器,因此我在本地计算机上使用了sshd,但它当然不会向我发送JSON。但这表明阅读有效:-)

    $ perl dummy.pl
    connected to the server
    ATTEMPT TO READ 4
    READ 'SSH-'
    ATTEMPT TO READ 1397966893
    ^C
    

    对服务器的示例响应的输出为:

    JSON:   {"type":0,"point":[5,4]}
    PACKET: 000000187b2274797065223a302c22706f696e74223a5b352c345d7d
    

    关于perl - Perl套接字编程发送方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54567530/

    相关文章:

    perl - 在此处的文档中插入常量的首选方法是什么?

    c - 为什么我写的这个服务器没有检测到客户端已经关闭了它的套接字?

    c++ - 当服务器重新启动并且客户端收到 WSAECONNRESET 错误代码时,我是否应该重新创建整个套接字

    java - 使用 0 值调用 setSoLinger 与根本不启用 soLinger 有什么区别?

    perl - Perl 中的冒号是什么意思?

    perl - 'ne' 在 do-while 循环中不起作用,而 '!=' 起作用

    windows - 如何在 Windows 上使用 Perl 确定操作系统的位数?

    mysql - Perl/MySQL 关系查询

    c - Socket编程PF包套接字

    c# - 离开多播组时通知