Основным элементом моего проекта является соединение через локальную сеть между двумя приложениями (клиентским и серверным) с использованием сокетов. Я следил за многими учебными пособиями, и наиболее стабильная версия - та, которую я собираюсь опубликовать ниже.

  • Я запускал его в консольных приложениях С #, и он отлично работает
  • Я запустил его в приложении Windows Forms, и он отлично работает

Итак, я был готов реализовать его в своем приложении Xamarin, и однажды (впервые) это сработало. Я даже тестировал его на своем смартфоне Android (в качестве клиента) и UWP на Windows (в качестве сервера). После того первого раза это больше никогда не работало. Ни на моем рабочем столе, ни на моем ноутбуке. Я буквально ничего не изменил, и он перестал работать.

При первом прикосновении к сокетам и Xamarin я подумал, что это просто не работает. Но после этого разовое рабочее время. Так не должно быть.

< Сильный > НЕИСПРАВНОСТИ

Я попадаю в клиентские классы (ClientSocket) на ClientSocket.Connect -> _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);
        }
    }
}
0
ehem 1 Дек 2020 в 02:14

1 ответ

Лучший ответ

Мне удалось добиться правильного подключения, включив loopback, как сказал @ NicoZhi-MSFT.

Включили ли вы возможность обратной петли приложения uwp и возможности частной сети?

Проверьте это документ, чтобы включить цикл возврата этого приложения.

Я выполнил только команды для стороны сервера из этого link, и, похоже, он работает нормально. Но всегда есть Private Network.

Итак, если вы можете заставить приложение UWP запускать cmd commands каждый раз , когда сервер < / strong> необходимо запустить или настройками автоматическую задачу (следуя инструкциям по ссылке выше) должно быть хорошо.

СОВЕТ:

UWP не очень удобен для работы CMD commands, поэтому при необходимости любой может поискать UWP fulltrust или / и , установив внешнее приложение , которое запускается при необходимости в фоновом режиме .

Большое спасибо

0
ehem 4 Дек 2020 в 21:13