繁体   English   中英

c# Xamarin UWP/Android 服务器 - 客户端套接字 tcp 无法正确连接

[英]c# Xamarin UWP/Android server - client socket tcp can't connect properly

我项目的核心元素是使用 sockets 在两个应用程序(客户端和服务器)之间通过本地网络连接。 我已经学习了很多教程,最稳定的版本是我将在下面发布的版本。

  • 我已经在 c# 控制台应用程序上运行它,它工作正常
  • 我已经在 Windows Forms 应用程序上运行它,它工作正常

所以我准备在我的 Xamarin 应用程序上实现它,并且有一次(第一次)它起作用了。 我什至在我的 android 智能手机(作为客户端)和 UWP 上测试了它在 windows(作为服务器)上。 在第一次之后,它再也没有工作过。 在我的台式机和笔记本电脑上都没有。 我实际上什么都没改变,它停止工作。

在我第一次接触 sockets 和 Xamarin 时,我认为它只是不起作用。 但在那之后的工作时间。 一定不是这样。

故障排除

我在 ClientSocket.Connect -> _socket.BeginConnect = false 上获取客户端类( ClientSocket )

  1. 我已经检查了防火墙,我已经卸载并禁用了防火墙
  2. 我已经检查了清单,即使在(必须拥有的权限)之后我尝试启用所有权限。

我会尝试上传一个保管箱链接(用于我的文件)

服务器代码

namespace Control
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class HomePage : ContentPage
    {
        public HomePage()
        {
            InitializeComponent();    
        }

        private  void ServerConnectBtn_Clicked(object sender, EventArgs e)
        {
            ServerSocket.Bind(9000);
            ServerSocket.Listen(500);
            ServerSocket.Accept();

            msg_lbl.Text = PacketHandler.status;
        }
    }
}

我的服务器类:

namespace Control.Server
{
    class ServerSocket
    {
        private static Socket _socket;

        private static byte[] _buffer = new byte[1024];
        public ServerSocket()
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public static void Bind(int port)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socket.Bind(new IPEndPoint(IPAddress.Any, port));
        }

        public static void Listen(int backlog)
        {
            _socket.Listen(500);
        }

        public static void Accept()
        {
            _socket.BeginAccept(AcceptedCallback, null);
        }

        private static void AcceptedCallback(IAsyncResult result)
        {
            Socket clientSocket = _socket.EndAccept(result);
            
            _buffer = new byte[1024];
            clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
            Accept();
        }

        private static void ReceivedCallback(IAsyncResult result)
        {
            Socket clientSocket = result.AsyncState as Socket;

            int bufferSize = clientSocket.EndReceive(result);

            byte[] packet = new byte[bufferSize];
            Array.Copy(_buffer, packet, packet.Length);

            //Handle the packet
            PacketHandler.Handle(packet, clientSocket);


            _buffer = new byte[1024];
            clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
        }
    }
}

namespace Control.Server
{
    public abstract class PacketStructure
    {
        private byte[] _buffer;
        public PacketStructure(ushort length, ushort type)
        {
            _buffer = new byte[length];
            WriteUshort(length, 0);
            WriteUshort(type, 2);
        }

        public PacketStructure(byte[] packet)
        {
            _buffer = packet;
        }

        public void WriteUshort(ushort value, int offset)
        {
            byte[] tempbuffer = new byte[2];
            tempbuffer = BitConverter.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset, 2);
        }

        public short ReadUshort(int offset)
        {
            return BitConverter.ToInt16(_buffer, offset);
        }

        public void WriteUint(uint value, int offset)
        {
            byte[] tempbuffer = new byte[4];
            tempbuffer = BitConverter.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset,4);
        }
        public void WriteString(string value, int offset)
        {
            byte[] tempbuffer = new byte[value.Length];
            tempbuffer = Encoding.UTF8.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset, value.Length);
        }

        public string ReadString(int offset, int count)
        {
            return Encoding.UTF8.GetString(_buffer, offset, count);
        }

        public byte[] Data {  get { return _buffer; } }
    }
}


namespace Control.Server
{
    public static class PacketHandler
    {
        public static string status;
        public static void Handle(byte[] packet, Socket clientSocket)
        {
            ushort packetLength = BitConverter.ToUInt16(packet, 0);
            ushort packetType = BitConverter.ToUInt16(packet, 2);

            status = "Received packet! Length: "+ packetLength + " | Type: "+ packetType;

            switch (packetType)
            {
                case 2000:
                    Message msg = new Message(packet);
                    Console.WriteLine(msg.Text);
                    break;
            }
        }
    }
}



namespace Control.Server
{
    public class Message : PacketStructure
    {

        private string _message;
        public Message(string message)
            : base((ushort)(4 + message.Length), 2000)
        {
            Text = message;
        }

        public Message(byte[] packet)
            : base(packet)
        {

        }
        public string Text
        {
            get { return ReadString(4, Data.Length - 4); }
            set
            {
                _message = value;
                WriteString(value, 4);
            }
        }
    }
}

客户端代码:

namespace Remote
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class SettingsPage : ContentPage
    {
        public SettingsPage()
        {
            InitializeComponent();
        }

        private void ClientConnectBtn_Clicked(object sender, EventArgs e)
        {
            ClientSocket.Connect("192.168.1.17",9000);
            Status_lbl.Text = "Status : " +ClientSocket.status;
        }

        private void Send_Clicked(object sender, EventArgs e)
        {
            string msg = msgEntry.Text;
            Message packet = new Message(msg);
            ClientSocket.Send(packet.Data);
            Status_lbl.Text = "Status : " + ClientSocket.status;
        }
    }
}

客户端类

namespace Remote.Client
{
    public abstract class PacketStructure
    {
        private byte[] _buffer;
        public PacketStructure(ushort length, ushort type)
        {
            _buffer = new byte[length];
            WriteUshort(length, 0);
            WriteUshort(type, 2);
        }

        public PacketStructure(byte[] packet)
        {
            _buffer = packet;
        }

        public void WriteUshort(ushort value, int offset)
        {
            byte[] tempbuffer = new byte[2];
            tempbuffer = BitConverter.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset, 2);
        }

        public short ReadUshort(int offset)
        {
            return BitConverter.ToInt16(_buffer, offset);
        }

        public void WriteUint(uint value, int offset)
        {
            byte[] tempbuffer = new byte[4];
            tempbuffer = BitConverter.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset, 4);
        }
        public void WriteString(string value, int offset)
        {
            byte[] tempbuffer = new byte[value.Length];
            tempbuffer = Encoding.UTF8.GetBytes(value);
            Buffer.BlockCopy(tempbuffer, 0, _buffer, offset, value.Length);
        }

        public string ReadString(int offset, int count)
        {
            return Encoding.UTF8.GetString(_buffer, offset, count);
        }

        public byte[] Data { get { return _buffer; } }
    }
}

   
namespace Remote.Client
{
    public class Message : PacketStructure
    {

        private string _message;
        public Message(string message)
            :base((ushort)(4 + message.Length), 2000)
        {
            Text = message;
        }

        public Message(byte[] packet)
            :base(packet)
        {

        }
        public string Text
        {
            get { return ReadString(4, Data.Length - 4); }
            set
            {
                _message = value;
                WriteString(value, 4);
            }
        }
    }
}


namespace Remote.Client
{
    class ClientSocket
    {
        private static Socket _socket;
        private static byte[] _buffer;
        public static string status;

        public ClientSocket()
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public static void Connect(string ipAddress, int port)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ipAddress), port), ConnectCallback, null);
        }

        private static void ConnectCallback(IAsyncResult result)
        {
            if (_socket.Connected)
            {
                status = "Connected to the server!";
                _buffer = new byte[1024];
                _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceiveCallback, null);
               // throw new Exception("Conencted");

            }
            else
            {
                
                status = "Could not connect";
              //  throw new Exception("Could not connect");
            }
        }

        private static void ReceiveCallback(IAsyncResult result)
        {
            int bufLength = _socket.EndReceive(result);
            byte[] packet = new byte[bufLength];
            Array.Copy(_buffer, packet, packet.Length);

            //Handle packet

            _buffer = new byte[1024];
            _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceiveCallback, null);
        }

        public static void Send(byte[] data)
        {
            _socket.Send(data);
        }
    }
}

正如@NicoZhi-MSFT 所说,我设法通过启用loopback回来实现正确的连接。

您是否启用了 uwp 应用的环回和专网功能?

请检查此文档以启用此应用程序循环返回

我只这个链接运行了服务器端的命令,它似乎工作得很好。 但是通过始终启用Private Network

因此,如果您可以让UWP应用程序在每次服务器需要启动运行cmd commands或者通过设置自动任务(按照上面链接的说明) ,应该没问题。

小费:

UWP 在运行CMD commands不是很方便,因此如果需要任何人都可以查找UWP fulltrust或/和设置在需要时在后台运行的外部应用程序

非常感谢

暂无
暂无

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

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