【问题标题】:c# Xamarin UWP/Android server - client socket tcp can't connect properlyc# Xamarin UWP/Android 服务器 - 客户端套接字 tcp 无法正确连接
【发布时间】:2021-03-12 21:41:00
【问题描述】:

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

  • 我已经在 c# 控制台应用程序上运行了它,它运行良好
  • 我已经在 Windows 窗体应用程序上运行它,它运行良好

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

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

疑难解答

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

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

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

服务器代码

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

【问题讨论】:

  • 你开启了uwp app的环回和私网能力吗?
  • 我对这一切都很陌生,所以...我知道专用网络,包清单上的环回也是吗?
  • 请检查此document 以启用此应用程序循环。
  • 我会试一试,我会回帖,但据我所知,环回只会对在同一设备上运行的应用程序有帮助。我的目标是让它在本地网络中的任何设备上工作
  • 如果它在本地网络中运行,您需要启用私有网络功能。你做到了吗?

标签: c# sockets xamarin tcp uwp


【解决方案1】:

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

你是否开启了 uwp 应用的环回和私网功能?

请检查此document 以启用此应用程序循环

我只运行了 服务器端的命令 来自 link,它似乎工作得很好。但是始终启用Private Network

所以如果你可以让UWP应用运行cmd commands每次服务器需要开始 通过设置自动任务 (按照上面链接的说明)应该没问题。

提示:

UWP 在运行 CMD commands 时不是很方便,所以如果需要任何人都可以寻找UWP fulltrust 或/并且通过设置一个在需要时在后台运行

的外部应用程序

非常感谢

【讨论】:

  • 就我而言,UWP 似乎有很多限制,我没有足够的时间或知识来绕过,所以我将切换到 Windows 窗体,也许会回到它稍后
猜你喜欢
  • 1970-01-01
  • 2013-12-05
  • 2014-05-21
  • 2017-11-23
  • 2015-10-04
  • 1970-01-01
  • 2015-08-21
  • 2017-02-24
  • 2011-04-09
相关资源
最近更新 更多