使用Eneter消息传递和协议缓冲区通过3g网络在端口80上启动tcp服务器的权限被拒绝

时间:2018-10-15 19:41:28

标签: java android sockets tcp protocol-buffers

我正在一个项目中,我的android应用程序应充当其他android客户端的服务器..我正在使用Eneter messaging framework,它在wifi上使用Sockets和Google Protobuf ..一旦我切换到3g网络(尝试使用电话的3g公共ip地址和端口80/81启动服务器),我会收到以下错误消息:EACCES(权限被拒绝)

E/EneterMessaging: ~24216 eneter.messaging.messagingsystems.tcpmessagingsystem.internal.TcpListenerProvider.startListening TcpListenerProvider  failed to start listening.
                   Exception:
                   java.net.BindException: bind failed: EACCES (Permission denied)
                   libcore.io.IoBridge.bind(IoBridge.java:99)
                   java.net.PlainSocketImpl.bind(PlainSocketImpl.java:132)
                   java.net.ServerSocket.bind(ServerSocket.java:335)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.NoneSecurityServerFactory.createServerSocket(NoneSecurityServerFactory.java:51)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.internal.TcpListenerProvider.startListening(TcpListenerProvider.java:123)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.TcpInputConnector.startListening(TcpInputConnector.java:134)
                   eneter.messaging.messagingsystems.simplemessagingsystembase.internal.DefaultDuplexInputChannel.startListening(DefaultDuplexInputChannel.java:96)
                   eneter.messaging.infrastructure.attachable.internal.AttachableDuplexInputChannelBase.attachDuplexInputChannel(AttachableDuplexInputChannelBase.java:40)
                   com.inactivity.magamine.teatime.services.TCPService.StartServer(TCPService.java:261)
                   com.inactivity.magamine.teatime.services.TCPService$6.run(TCPService.java:279)
                   java.lang.Thread.run(Thread.java:818) 

我的清单中有以下权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET"/>

这是启动服务器的代码:

public void StartServer() throws Exception
    {
        // Create sender sending MyRequest and as a response receiving MyResponse
        // Instantiate Protocol Buffer based serializer.
        ISerializer aSerializer = new ProtoBufSerializer();

        // Create sender sending MyRequest and as a response receiving MyResponse
        // The sender will use Protocol Buffers to serialize/deserialize messages.
        IDuplexTypedMessagesFactory aRecieverFactory = new DuplexTypedMessagesFactory(aSerializer);
        myReceiver = aRecieverFactory.createDuplexTypedMessageReceiver(MessageDeclarations.MyMsg.class, MessageDeclarations.MyMsg.class);
        myReceiver.messageReceived().subscribe(myOnRequestHandler);

        if(aMessaging == null)aMessaging = new TcpMessagingSystemFactory();

        IDuplexInputChannel anInputChannel
                = aMessaging.createDuplexInputChannel(Service_URL);//Service_URL = "tcp://xxx.xxx.x.xx:80/ with public ip adress


        // Attach the output channel to the sender and be able to send
        // messages and receive responses.
        myReceiver.attachDuplexInputChannel(anInputChannel);

        isConnected = true;
        showNotification("Server Started","url: "+Service_URL,Color.GREEN);
    }

该异常发生在

myReceiver.attachDuplexInputChannel(anInputChannel);

那是Eneter启动套接字服务器的地方。

  

编辑:从this中,我发现要绑定<1024端口需要root特权。因此,我尝试使用1025、8080、8081这样的端口   而是出现以下例外情况:无法分配请求的地址,是   我不能使用3G网络公共IP地址启动套接字服务器   还是我错过了什么?

E/EneterMessaging: ~25710 eneter.messaging.messagingsystems.simplemessagingsystembase.internal.DefaultDuplexInputChannel.startListening DefaultDuplexInputChannel 'tcp://105.66.131.38:8080/'  failed to start listening.
                   Exception:
                   java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
                   libcore.io.IoBridge.bind(IoBridge.java:99)
                   java.net.PlainSocketImpl.bind(PlainSocketImpl.java:132)
                   java.net.ServerSocket.bind(ServerSocket.java:335)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.NoneSecurityServerFactory.createServerSocket(NoneSecurityServerFactory.java:51)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.internal.TcpListenerProvider.startListening(TcpListenerProvider.java:123)
                   eneter.messaging.messagingsystems.tcpmessagingsystem.TcpInputConnector.startListening(TcpInputConnector.java:134)
                   eneter.messaging.messagingsystems.simplemessagingsystembase.internal.DefaultDuplexInputChannel.startListening(DefaultDuplexInputChannel.java:96)
                   eneter.messaging.infrastructure.attachable.internal.AttachableDuplexInputChannelBase.attachDuplexInputChannel(AttachableDuplexInputChannelBase.java:40)
                   com.inactivity.magamine.teatime.services.TCPService.StartServer(TCPService.java:261)
                   com.inactivity.magamine.teatime.services.TCPService$6.run(TCPService.java:279)
                   java.lang.Thread.run(Thread.java:818)

感谢您的帮助。

亲切

2 个答案:

答案 0 :(得分:1)

原始问题的答案

端口分配失败,因为您注意到80是特权端口。

回答更新的问题

IP地址分配失败,因为事实证明,您在代码中输入了错误的IP地址。一旦关闭Wi-Fi网络(大概)进入移动网络,您正在使用的地址就会从系统中删除,并且无线运营商会为您分配其他地址。实际上,使用0.0.0.0会告诉您的服务器库“我想在所有接口上进行监听”。 (另一种选择是找出您的移动IP地址,然后使用它。)但是,这使我们遇到了最后一个问题:

对您当前问题的评论

它没有连接可能有很多原因。我怀疑它可能是NAT,如this question中所述。长话短说,很少有应用程序(如果有)使用您选择的体系结构(在连接到移动网络的订户手机上运行服务器)。由于存在NAT,手机几乎总是必须“拨出”才能形成连接(在移动网络上)。而且您的服务器没有拨出;在听。

只要您未跨越NAT边界,这些限制将不适用于您的本地WiFi网络。

要解决此问题,您可能需要了解网络体系结构以及一些网络调试方面的培训。诸如Wireshark之​​类的捕获工具是一个很大的帮助。

如果您需要更多帮助,而SO上的其他答案都没有帮助,那么最好是提一个新问题。

答案 1 :(得分:1)

更新:我已修复

  

感谢您的澄清,link   有用。

从wifi切换到3G后,网络运营商会为电话分配一个专用IP地址10.xx.xx.xx,该地址随后会由NAT转换为共享的公共IP地址。

如果所有节点(试图互相连接的电话)都在同一ISP上,并且-(不确定此节点的有效性)-与我的情况相对接近,使用应该使用分配的ISP地址(在我的情况下为10.xx.xx.xx )代替公用IP地址。

我用它来获取有效的IP地址:

public String getAndroidIP() {
        try {
            String interfaces = "";
            for (Enumeration<NetworkInterface> en = NetworkInterface
                    .getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf
                        .getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()
                            && inetAddress instanceof Inet4Address) {

                        interfaces = interfaces
                                + inetAddress.getHostAddress().toString();
                        Log.d("interface NET",interfaces);
                    }
                    Log.d("interface Adress",inetAddress.getHostAddress().toString());
                }
            }
            return (interfaces);
        } catch (SocketException ex) {
            Log.d("getAndroidIP", ex.toString());
        }
        return null;
    }
  

但是,我应该在不同的运营商和不同的环境下对其进行测试   确保手机不会共享同一3G天线的位置。生病   当我得到结果时对其进行编辑。

谢谢。