关于 java:doInBackground 卡住

doInBackground gets stuck

我正在尝试创建一个使用多个端口的服务器,以便可以轻松地发送和接收不同的数据和信息,但是在我的 doInBackground 方法中,我的代码卡在了 socket.receive 上,
这是我的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
while( run )
    {
        //GameServerID
        try
        {
            if(gameServerID == null)
            {
                gameServerID = new DatagramSocket( portID );
            }
            //try to receive data
            byte[] buf = new byte[256];
            DatagramPacket packet = new DatagramPacket( buf, buf.length );
            try
            {
                Log.d(TAG,"Wait for something to connect");
                gameServerID.receive( packet ); <--GETS STUCK HERE
            }
            catch (IOException e)
            {
                Log.d(TAG,"Error with receiving data");
                e.printStackTrace();
            }
            String data = new String( buf, 0, packet.getLength() );
            Log.d(TAG, data);
            //Send out the ID to the client
            byte[] bufer = new byte[256];
            //Send a message"connect" to the host
            String msg = Integer.toString( players );
            players = players + 1;
            bufer = msg.getBytes();
            InetAddress address;
            //Default ip address of the host
            address = packet.getAddress();
            DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, portID );
            //Send packet
            gameServerID.send( p );
            addresses.add( address );
        }
        catch (SocketException e)
        {
            Log.d(TAG,"Error with socket");
            e.printStackTrace();
        }
        //Listen for a client to connect
        catch (IOException e)
        {
            Log.d(TAG,"Error with I/O");
            e.printStackTrace();
        }

        //GameServerPositions
        try
        {
            Log.d(TAG,"Run the gamePositions code");
            if(gamePositions == null)
            {
                gamePositions = new DatagramSocket( portPos );
            }
            //Receive position
            //try to receive data
            byte[] buf = new byte[256];
            DatagramPacket packet = new DatagramPacket( buf, buf.length );
            try
            {
                gamePositions.receive( packet );
            }
            catch (IOException e)
            {
                Log.d(TAG,"Error with receiving data");
                e.printStackTrace();
            }
            String data = new String( buf, 0, packet.getLength() );
            Log.d(TAG, data);
            String[] pos = data.split(":");
            for(int i = 0;i<pos.length;i++)
            {
                Log.d(TAG, pos[i]);
            }
            xValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[1] );
            yValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[2] );
        }
        catch (SocketException e)
        {
            Log.d(TAG,"Error with socket");
            e.printStackTrace();
        }
        //Listen for a client to connect
        catch (IOException e)
        {
            Log.d(TAG,"Error with I/O");
            e.printStackTrace();
        }

        //GameServerSendPos
        try
        {
            Log.d(TAG,"Run the gamePositionsSend code");
            String data ="";
            if( gameSendPos == null )
            {
                gameSendPos = new DatagramSocket( portSend );
            }

            //create the string ready to be sent out
            for(int i = 0; i < 8; i++)
            {
                if(xValues[i] >= 0)
                {
                    data += i +":" + xValues[i] +":" + yValues[i] +":";
                }
            }

            byte[] bufer = new byte[256];
            bufer = data.getBytes();
            DatagramPacket p = null;

            for(int i = 0;i < addresses.size(); i++)
            {
                if( addresses.get(i) != null )
                {
                    p = new DatagramPacket( bufer, bufer.length , addresses.get(i), portSend );
                    gameSendPos.send( p );
                }
            }

        }
        catch (SocketException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

我能做些什么来阻止它卡住,或者在等了这么久之后,只是跳过它?只是为了获取更多信息,当第一个客户端连接时,代码工作正常,直到它再次到达顶部,然后 socket.received 就卡住了......

画布

更新

我已将我的代码更改为 3 个不同的类,我在我的服务器中启动它们,而循环就像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while( run )
    {
        if(start == true)
        {
            gsID.doInBackground( );
            addresses = gsID.addresses;
            gsPos.addresses = addresses;
            gsPos.doInBackground( );
            gsSendPos.addresses = addresses;
            gsSendPos.positions = gsPos.positions;
            gsSendPos.doInBackground( );
            start = false;
        }
        else
        {
            addresses = gsID.addresses;
            gsPos.addresses = addresses;
            gsSendPos.addresses = addresses;
            gsSendPos.positions = gsPos.positions;
        }
    }

但它仍然再次卡在 gameServerID 接收方法上。

我只是将我的所有类都更改为线程,它工作得更好,但在更高版本的 android 4.0 中,线程不能从 UI 使用,但我不确定如何从非 UI 启动它们?


来自 DatagramSocket.receive 的 Javadoc:

This method blocks until a datagram is received

所以您的代码"卡住"了,因为它正在等待数据包到达。这意味着连接到此服务器/端口的客户端尚未发送另一个数据包,因此套接字被设计为阻塞。

传统上,如果您想同时监听多个端口,您有两种选择:

  • 在不同的线程上打开每个阻塞套接字(如果由于每个线程一个客户端而同时有大量客户端,这将无法很好地扩展,但对于少量连接可以正常工作)
  • 使用 NIO,它是 Java 的非阻塞 IO