【问题标题】:C# server Socket to Android Socket over NAT通过 NAT 的 C# 服务器 Socket 到 Android Socket
【发布时间】:2014-06-19 09:01:53
【问题描述】:

Android 应用位于 NAT(3G 连接)之后,而服务器位于公共 IP 上。

Android 应用可以连接到服务器套接字并发送数据(通过 android 上的 Socket/TCPclient),但由于 NAT,服务器无法连接到 Android 端口 (服务器获取“...未能响应“ip_adress_of_android : port_that_is_open_and_listening_on_android”。

有没有办法克服这个问题,或者我可以使用一些参数来让服务器连接尝试通过 NAT 到达目的地而不使用自定义库? - 或者你能否指点我一个易于实施的方法,我没有时间研究和集成复杂的 3rd 方库

这是我的服务器代码如何工作的示例:

int port_server, port_android;  // used to declare used ports by the server and android   
Socket server_socket, client_socket; //sockets used to receive and send data

server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                           
server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));                                                        
server_socket.Listen(0);

public void listen()
{
server_socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}

private void AcceptCallback(IAsyncResult AR)
{
                client_socket = server_socket.EndAccept(AR);                                                                            
                buffer = new byte[client_socket.ReceiveBufferSize];                                                                     
                client_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}

private void ReceiveCallback(IAsyncResult AR)
        {
        listen(); // to continue listening to the port
        // code that does something with the data
        send_string("Take this"); // sends a string to android
        }
public void send_string(string notif)
        {
            string ip_client = client_socket.RemoteEndPoint.ToString();                                                  
            string ip_client2 = (ip_c.Split(':'))[0];                                                               
            TcpClient client = new TcpClient(ip_client, port_android);                                             
            Byte[] notifi = System.Text.Encoding.ASCII.GetBytes(notif);                                   
            NetworkStream stream = client.GetStream();                                                              
            stream.Write(notifi, 0, notifi.Length);                                                         
            stream.Close();                                                                                         
            client.Close();                                                                                         
        }

我应该注意它们在 LAN 上可以双向工作,所以代码可以正常工作,我只需要修改它,以便它可以通过 NAT 到达 android 目标。

【问题讨论】:

  • 您可以通过client_socket发回数据。没有办法突破 NAT,除非 NAT 配置了端口转发。但是一旦建立连接,您就可以通过两种方式传输数据。
  • 你的意思是我可以通过Android建立的连接将数据发送回服务器?如何?我无法在连接的服务器端获得任何选项来将字符串放入其中。

标签: java c# android sockets nat


【解决方案1】:

类似的东西

class Program
{
    int port_server = 42424;
    Socket server_socket;

    public Program()
    {
        server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));
        server_socket.Listen(0);
    }

    public void Listen()
    {
        while (true)
        {
            var client = server_socket.Accept();
            var buffer = new byte[client.ReceiveBufferSize];
            client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Tuple.Create(client, buffer));
        }
    }

    private void ReceiveCallback(IAsyncResult AR)
    {
        var state = (Tuple<Socket, byte[]>)AR.AsyncState;
        var client = state.Item1;
        var buffer = state.Item2;
        byte[] notifi = System.Text.Encoding.ASCII.GetBytes("Take this");
        client.Send(notifi);
        client.Close();
    }



    static void Main(string[] args)
    {
        var programm = new Program();
        programm.Listen();
    }
}

客户端部分

using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
    client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 42424));
    client.Send(new byte[] {1, 2, 3}, SocketFlags.None);
    byte[] bt = new byte[256];
    client.Receive(bt, 256, SocketFlags.None);
}

【讨论】:

  • 非常感谢您的回复!