代码之家  ›  专栏  ›  技术社区  ›  Bailey Miller

使用BinaryReader/Writer的C#套接字从读取器获取错误数据

  •  0
  • Bailey Miller  · 技术社区  · 7 年前

    我正在为类处理一个项目,我必须创建一个套接字服务器,然后创建一堆从队列请求票证的假客户端。我所有的工作都很好,但是,当我从套接字流中读取我的票证对象时,我只收到发送的第一个对象。

    在那条线上 Console.WriteLine($"ID {paramData.ClientID} got ticket {tick.TicketID} for show {tick.EventName}");

    我有一些想法,但我只是不知道为什么会这样。首先,通过套接字发送第一个票证,然后每次都重新使用该票证,但我不确定为什么会发生这种情况,因为在发送之前我先将一个票证出列。

    另一个想法是,我只是做线程完全错误,但我不明白如何相同的票显示在不同的线程。

    enter image description here

    class Program
    {
        static ConcurrentQueue<Ticket> _TicketStorage = new ConcurrentQueue<Ticket>();
        static Socket ServerSocket;
    
        static void Main(string[] args)
        {
            Console.WriteLine("Starting Server ...");
    
            // Gets the event name to apply to all the tickets
            Console.Write("Enter Name of Event: ");
            var eventName = Console.ReadLine();
    
            // Allows the user to set the ticket count or defaults to 500
            Console.Write("\nEnter Max Number of Tickets (Default: 500): ");
            var ticketCountTry = int.TryParse(Console.ReadLine(), out int TicketCountResult);
    
            // Setups up the ticket q
            Console.WriteLine("Initilizing Ticket Storage");
            for (int i = 0; i < (ticketCountTry ? TicketCountResult : 5); i++)
            {
                _TicketStorage.Enqueue(new Ticket(eventName, i));
            }
    
            Console.Clear();
    
            // Finish line for application
            Console.WriteLine("Server is ready to process requests");
    
            var ServerThread = Task.Factory.StartNew(()=> 
            {
                StartServerListener();
            },TaskCreationOptions.LongRunning);
    
            StartFakeClients();
    
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    
        static void StartFakeClients()
        {
            Console.Write("Enter number of tickets to attempt to purchase (Default: 600): ");
            var attemptNumberTry = int.TryParse(Console.ReadLine(), out int attemptAmount);
    
            // Setup all the connections to be in the ready state
            for (int i = 0; i < (attemptNumberTry ? attemptAmount : 10); i++)
            {
                ThreadPool.QueueUserWorkItem(FakeClientWorker, new
                {
                    ClientID = i
                });
    
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }
        }
    
        static void FakeClientWorker(object state)
        {
            dynamic paramData = state;
    
            // Create a connection to the server
            var Connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Connection.Connect(IPAddress.Loopback, 11000);
    
    
            using (var bReader = new BinaryReader(new NetworkStream(Connection, true), Encoding.UTF8, false))
            {
                // Create my high level reader to parse incoming data
                var dataBlock = bReader.ReadString();
    
                if (!string.IsNullOrEmpty(dataBlock))
                {
                    Ticket tick = JsonConvert.DeserializeObject<Ticket>(dataBlock);
                    Console.WriteLine($"ID {paramData.ClientID} got ticket {tick.TicketID} for show {tick.EventName}");
                }
                else
                {
                    // Didn't get a ticket
                    Console.WriteLine($"ID {paramData.ClientID} didn't get a ticket");
                }
            }
        }
    
        static void StartServerListener()
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);
    
            ServerSocket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
            ServerSocket.Bind(localEndPoint);
            ServerSocket.Listen(100);
    
            while (true)
            {
                var clientSocket = ServerSocket.Accept();
    
                // You just got a new client asking for a ticket
                // Send this connection to another thread and then continue listening for connections
                ThreadPool.QueueUserWorkItem(DoServerWork, clientSocket);
            }
        }
    
        static void DoServerWork(object clientSocket)
        {
            // Get the next ticket from the q
            var hasNewTickets = _TicketStorage.TryDequeue(out Ticket EventTicket);
    
            // Start a writer
            var n = new NetworkStream((Socket)clientSocket, false);
            using (var bWriter = new BinaryWriter(new NetworkStream((Socket)clientSocket, true), Encoding.UTF8, false))
            {
                // I have my writer now I need to send this data
                bWriter.Write((hasNewTickets ? JsonConvert.SerializeObject(EventTicket) : String.Empty));
            } // Dispose of the advanced network stream, Dispose of the binary writer, close the connection
        }
    }
    
    /// <summary>
    /// A structure for storing information about an event
    /// </summary>
    public class Ticket
    {
        /// <summary>
        /// Unique identifer for the ticket 
        /// </summary>
        public readonly int TicketID;
    
        /// <summary>
        /// Event name this ticket represents
        /// </summary>
        public readonly String EventName;
    
        public Ticket(String EventName, int ID)
        {
            this.EventName = EventName;
            TicketID = ID;
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   vasily.sib    7 年前

    我相信,这不是 “二进制读写器问题” JsonConvert (来自 Json.Net 我想)对你的对象进行序列化和反序列化。我想如果你调试你的项目,你会发现 dataBlock 传递给 JsonConvert.DeserializeObject<Ticket>() 方法很好。

    真正的原因是 Ticket JSONVERT公司 将尝试将构造函数参数名称与JSON中的值匹配。所以你才对 EventName TicketID (0). 尝试将构造函数更改为:

    public Ticket(String EventName, int TicketID)
    {
        this.EventName = EventName;
        this.TicketID = TicketID;
    }