Я работаю над проектом для класса, и мне нужно создать сервер сокетов, а затем группу поддельных клиентов, которые запрашивают билеты из очереди.У меня все это работает нормально, однако, когда я читаю свой объект Ticket из потока Socket, я получаю только первый отправленный объект.
В строке Console.WriteLine($"ID {paramData.ClientID} got ticket {tick.TicketID} for show {tick.EventName}");
я получаю свой уникальный идентификатор клиента, который генерируется во время цикла for, однако каждый раз получаю идентификатор билета, равный 0.
У меня есть несколько мыслей, но я просто не уверен, почему это происходит.Во-первых, отправляет первый билет через сокет, а затем повторно использует этот билет каждый раз, но я не уверен, почему это произойдет, потому что я удаляю один из них перед отправкой.
Еще одна мысль - я просто неправильно выполняю потоки, но не понимаю, как один и тот же тикет отображается в разных потоках.
Вот скриншот выполненного кода с 10попыток покупки и 5 доступных билетов
Весь код:
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;
}
}