简体   繁体   English

使用Eneter Messaging和Protocol Buffers在3g网络上的端口80上启动tcp服务器的权限被拒绝

[英]Permission denied to start tcp server on port 80 over 3g network using Eneter Messaging and Protocol Buffers

I'm working on a project where my android application should behave as a server for other android clients .. I'm using Eneter messaging framework which uses Sockets and Google Protobuf .. on wifi everything works like a charm but once I switch to 3g network (try to start server using phone's 3g public ip adress and port 80/81) I get the following error : EACCES (Permission denied) 我正在开发一个项目,我的android应用程序应该作为其他Android客户端的服务器。我正在使用Eneter消息框架 ,它使用Sockets和Google Protobuf ..在wifi上,一切都像魅力一样,但一旦切换到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) 

I have these permissions in my manifest: 我的清单中有这些权限:

<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"/>

and this is the code that starts the server: 这是启动服务器的代码:

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);
    }

The exception occurs on 发生异常

myReceiver.attachDuplexInputChannel(anInputChannel);

Thats where Eneter starts the socket server. 这是Eneter启动套接字服务器的地方。

EDIT: From this I found that to bind on ports < 1024 you need root privileges. 编辑:从这里我发现要绑定端口<1024你需要root权限。 So I tried ports like 1025, 8080, 8081 , I now get this exception instead: Cannot assign requested address , is it that I cant use 3G network public ip adress to start a socket server or am I missing something ? 所以我尝试了像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)

I will appreciate your help. 我将感谢你的帮助。

Kindly 和蔼

Answer to original question 回答原始问题

The port assignment is failing because, as you noted, 80 is a privileged port. 端口分配失败,因为正如您所指出的,80是特权端口。

Answer to updated question 回答更新的问题

The IP address assignment failed because, as it turned out, you had the wrong IP address in your code. IP地址分配失败,因为事实证明,您的代码中的IP地址错误。 Once you turned off your WiFi network (presumably) to get onto the mobile network, the address you were using was removed from the system, and you were assigned a different address by your wireless carrier. 关闭WiFi网络(大概)以进入移动网络后,您使用的地址已从系统中删除,并且您的无线运营商为您分配了不同的地址。 Using 0.0.0.0 essentially tells your server library, "I want to listen on all interfaces". 使用0.0.0.0实质上告诉您的服务器库,“我想在所有接口上监听”。 (The other option is to figure out your mobile IP address, and use that instead.) But that brings us to the last problem: (另一种选择是弄清楚你的移动IP地址,并使用它。)但这会带给我们最后一个问题:

A comment on your current issue 对您当前的问题发表评论

There could be a lot of reasons why it's not connecting. 可能有很多原因导致它无法连接。 I suspect it's probably NAT , as described in this question . 我怀疑它可能是NAT ,如本问题所述 Long story short, very few apps (if any), use the architecture you've chosen (running a server on a subscriber handset connected to the mobile network). 长话短说,很少有应用程序(如果有的话),使用您选择的架构(在连接到移动网络的用户手机上运行服务器)。 Because of NAT, handsets almost always have to "dial out" in order to form a connection (on a mobile network). 由于NAT,手机几乎总是必须“拨出”才能形成连接(在移动网络上)。 And your server isn't dialing out; 而你的服务器没有拨出; it's listening. 它正在倾听。

These limitations won't apply to your local WiFi network, as long as you're not crossing a NAT boundary. 只要您没有越过NAT边界,这些限制将不适用于您的本地WiFi网络。

To solve this problem, you'll probably need to know the network architecture, and some training in network debugging. 要解决这个问题,您可能需要了解网络架构以及网络调试方面的一些培训。 Capture tools like Wireshark are a big help. 像Wireshark这样的捕获工具是一个很大的帮助。

If you need more assistance on that, and none of the other answers on SO help you, it is probably best to start a new question. 如果您需要更多帮助,并且SO上的其他答案都没有帮助您,那么最好开始一个新问题。

UPDATE: I Fixed it 更新:我修复了它

Thank you greeble31 for your clarifications, this link was useful. 感谢greeble31的澄清,这个链接很有用。

After switching from wifi to 3G the network carrier assign to the phone a private IP address 10.xx.xx.xx which is later translated by NAT to a shared public IP address. 在从wifi切换到3G之后,网络运营商为电话分配专用IP地址10.xx.xx.xx,该IP地址稍后由NAT转换为共享公共IP地址。

If all nodes (phones trying to reach each others) are on the same ISP and - (not sure about effectiveness of this one) - are relatively close as in my case, using the assigned ISP address (in my case 10.xx.xx.xx ) instead of the public IP address should do the trick. 如果所有节点(试图联系彼此的电话)都在同一个ISP上并且 - (不确定这个节点的有效性) - 在我的情况下相对接近, 使用分配的ISP地址(在我的情况下为10.xx.xx) .xx )而不是公共IP地址应该做的伎俩。

I used this to get the working IP Address: 我用它来获取工作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;
    }

However, I should test it under different carriers and different locations to ensure the phone don't share the same 3G antenna. 但是,我应该在不同的运营商和不同的位置进行测试,以确保手机不共享相同的3G天线。 I'll edit this with the results as I get them. 我会用结果编辑它,因为我得到它们。

Thank you. 谢谢。

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

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