/// <summary> /// Fires right when a client is connected to the server. /// </summary> /// <param name="ar"></param> /// <remarks></remarks> public void ConnectToServerCompleted(IAsyncResult ar) { // get the async state object which was returned by the async beginconnect method SocketContainer co = ar.AsyncState.CastType <SocketContainer>(); // end the async connection request so we can check if we are connected to the server try { // call the EndConnect method which will succeed or throw an error depending on the result of the connection co.Socket.EndConnect(ar); //Send // at this point, the EndConnect succeeded and we are connected to the server! // send a welcome message IsConnected = true; OnConnectedCallback?.Invoke(); //Send(SocketManager.ManagedConn(), co); // ??? --> el problema estába en que estaba llamado a Socket.Send directamente y estamos dentro de un Socket async xD // start waiting for messages from the server //AsyncReceiveState mReceiveState = new AsyncReceiveState(); //mReceiveState.Socket = mState.Socket; Console.WriteLine("Client ConnectedToServer => CompletedSynchronously: {0}; IsCompleted: {1}", ar.CompletedSynchronously, ar.IsCompleted); co.Socket.BeginReceive(co.rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ServerMessageReceived), co); } catch (Exception ex) { // at this point, the EndConnect failed and we are NOT connected to the server! myLogger.Log("Connect error: " + ex.Message); } }
/// <summary> /// Initializes a new instance of the <see cref="SocketClient"/> class. /// </summary> /// <param name="ipAddr">The ip addr.</param> /// <param name="port">The port.</param> /// <param name="sType">Type of the s.</param> /// <param name="pType">Type of the p.</param> /// <param name="readEvery">The read every.</param> /// <param name="everyFunc">The every function.</param> /// <param name="doConnection">if set to <c>true</c> [do connection].</param> public SocketClient(IPAddress ipAddr, ushort port, SocketType sType, ProtocolType pType, Action <object, SocketContainer> everyFunc, bool doConnection = false) { //period = readEvery; cSendQueue.MessageQueued += cSendQueue_MessageQueued; ReceivedServerMessageCallback = everyFunc; //TimerCallback timerDelegate = new TimerCallback(Timering); //if (everyFunc != null) // task = new Timer(timerDelegate, null, 5, readEvery); IP = ipAddr; Port = port; //0 as an ID is not allowed, this is waiting for a ID my = new SocketContainer(0, new Socket(ipAddr.AddressFamily, sType, pType) { NoDelay = false }); if (doConnection) { DoConnection(); } }
public void ServerMessageReceived(IAsyncResult ar) { // get the async state object from the async BeginReceive method //AsyncReceiveState mState = (AsyncReceiveState)ar.AsyncState; SocketContainer co = ar.AsyncState.CastType <SocketContainer>(); // call EndReceive which will give us the number of bytes received int numBytesReceived = 0; numBytesReceived = co.Socket.EndReceive(ar); // determine if this is the first data received if (co.rState.ReceiveSize == 0) { // this is the first data recieved, so parse the receive size which is encoded in the first four bytes of the buffer co.rState.ReceiveSize = BitConverter.ToInt32(co.rState.Buffer, 0); // write the received bytes thus far to the packet data stream co.rState.PacketBufferStream.Write(co.rState.Buffer, 4, numBytesReceived - 4); } else { // write the received bytes thus far to the packet data stream co.rState.PacketBufferStream.Write(co.rState.Buffer, 0, numBytesReceived); } // increment the total bytes received so far on the state object co.rState.TotalBytesReceived += numBytesReceived; // check for the end of the packet // bytesReceived = Carcassonne.Library.PacketBufferSize Then if (co.rState.TotalBytesReceived < co.rState.ReceiveSize) { // ## STILL MORE DATA FOR THIS PACKET, CONTINUE RECEIVING ## // the TotalBytesReceived is less than the ReceiveSize so we need to continue receiving more data for this packet co.Socket.BeginReceive(co.rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ServerMessageReceived), co); } else { // ## FINAL DATA RECEIVED, PARSE AND PROCESS THE PACKET ## // the TotalBytesReceived is equal to the ReceiveSize, so we are done receiving this Packet...parse it! BinaryFormatter mSerializer = new BinaryFormatter(); // rewind the PacketBufferStream so we can de-serialize it co.rState.PacketBufferStream.Position = 0; // de-serialize the PacketBufferStream which will give us an actual Packet object co.rState.Packet = mSerializer.Deserialize(co.rState.PacketBufferStream); // parse the complete message that was received from the server ParseReceivedServerMessage(co.rState.Packet, co); // call BeginReceive again, so we can start receiving another packet from this client socket co.Socket.BeginReceive(co.rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ServerMessageReceived), co); //Dispose of everything we dont need after receive message from server Array.Clear(co.rState.Buffer, 0, co.rState.Buffer.Length); co.rState.ReceiveSize = 0; co.rState.Packet = null; co.rState.TotalBytesReceived = 0; co.rState.PacketBufferStream.Close(); co.rState.PacketBufferStream.Dispose(); co.rState.PacketBufferStream = new MemoryStream(); } }
private void MessageReceived(string argMessage, SocketContainer co) { if (txtReceiveLog.Text != "") { txtReceiveLog.Text = Environment.NewLine + txtReceiveLog.Text; } txtReceiveLog.Text = co.Socket.RemoteEndPoint.ToString() + ": " + argMessage + txtReceiveLog.Text; }
private void cSendQueue_MessageQueued() { // when a message is queued, we need to check whether or not we are currently processing the queue before allowing the top item in the queue to start sending if (cSendQueue.Processing == false) { // process the top message in the queue, which in turn will process all other messages until the queue is empty //AsyncSendState mState = (AsyncSendState)cSendQueue.Messages.Dequeue(); SocketContainer co = cSendQueue.Messages.Dequeue().CastType <SocketContainer>(); // we must send the correct number of bytes, which must not be greater than the remaining bytes co.Socket.BeginSend(co.sState.BytesToSend, co.sState.NextOffset(), co.sState.NextLength(), SocketFlags.None, new AsyncCallback(MessagePartSent), co); } }
public void ParseReceivedServerMessage(object obj, SocketContainer argContainer) { Console.WriteLine("Received object of type: {0}", obj.GetType().Name); if (obj is string) { myLogger.Log((string)obj); } else if (obj is SocketMessage) { HandleAction((SocketMessage)obj, argContainer); } }
public void Send(object obj, SocketContainer co) { // serialize the Packet into a stream of bytes which is suitable for sending with the Socket BinaryFormatter mSerializer = new BinaryFormatter(); using (MemoryStream mSerializerStream = new MemoryStream()) { mSerializer.Serialize(mSerializerStream, obj); // get the serialized Packet bytes byte[] mPacketBytes = mSerializerStream.GetBuffer(); // convert the size into a byte array byte[] mSizeBytes = BitConverter.GetBytes(mPacketBytes.Length + 4); // create the async state object which we can pass between async methods //AsyncSendState mState = new AsyncSendState(ClientSocket); // resize the BytesToSend array to fit both the mSizeBytes and the mPacketBytes // ERROR: Not supported in C#: ReDimStatement if (co.sState.BytesToSend != null) { if (co.sState.BytesToSend.Length != mPacketBytes.Length + mSizeBytes.Length) { Array.Resize(ref co.sState.BytesToSend, mPacketBytes.Length + mSizeBytes.Length); } } else { co.sState.BytesToSend = new byte[mPacketBytes.Length + mSizeBytes.Length]; } // copy the mSizeBytes and mPacketBytes to the BytesToSend array Buffer.BlockCopy(mSizeBytes, 0, co.sState.BytesToSend, 0, mSizeBytes.Length); Buffer.BlockCopy(mPacketBytes, 0, co.sState.BytesToSend, mSizeBytes.Length, mPacketBytes.Length); Array.Clear(mSizeBytes, 0, mSizeBytes.Length); Array.Clear(mPacketBytes, 0, mPacketBytes.Length); Console.WriteLine("Ready to send a object of {0} bytes length", co.sState.BytesToSend.Length); co.Socket.BeginSend(co.sState.BytesToSend, co.sState.NextOffset(), co.sState.NextLength(), SocketFlags.None, new AsyncCallback(MessagePartSent), co); } }
/// <summary> /// ClientConnected is a callback that gets called when the server accepts a client connection from the async BeginAccept method. /// </summary> /// <param name="ar"></param> /// <remarks></remarks> public void ClientAccepted(IAsyncResult ar) { // get the async state object from the async BeginAccept method, which contains the server's listening socket Socket mServerSocket = ar.AsyncState.CastType <Socket>(); // call EndAccept which will connect the client and give us the the client socket Socket mClientSocket = null; try { mClientSocket = mServerSocket.EndAccept(ar); } catch //(ObjectDisposedException ex) { // if we get an ObjectDisposedException it that means the server socket terminated while this async method was still active return; } // instruct the client to begin receiving data //In the very first connection we have to send the id to the client ulong genID = 1; //Give id in a range... bool b = routingTable.Keys.FindFirstMissingNumberFromSequence(out genID, new MinMax <ulong>(1, (ulong)routingTable.Count)); myLogger.Log("Adding #{0} client to routing table!", genID); //Esto ni parece funcionar bien SocketContainer co = new SocketContainer(genID, mClientSocket); if (!routingTable.ContainsKey(genID)) { routingTable.Add(genID, co); } else { Console.WriteLine("Overlapping ID error!"); } //We don't have a way to know if there was a problem in the transmission ??? SendToClient(SocketManager.ReturnClientIDAfterAccept(genID), routingTable[genID]); ClientConnected?.Invoke(routingTable[genID]); routingTable[genID].Socket.BeginReceive(routingTable[genID].rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ClientMessageReceived), routingTable[genID]); //ClientMessageReceived // begin accepting another client connection mServerSocket.BeginAccept(new AsyncCallback(ClientAccepted), mServerSocket); }
private void HandleAction(SocketMessage sm, SocketContainer argContainer) { //Before we connect we request an id to the master server... if (sm.msg is SocketCommand) { SocketCommand cmd = sm.msg.CastType <SocketCommand>(); if (cmd != null) { switch (cmd.Command) { /*case SocketCommands.CreateConnId: * myLogger.Log("Starting new CLIENT connection with ID: {0}", sm.id); * Id = sm.id; * * Send(SocketManager.ConfirmConnId(Id), argContainer); //??? * OnConnectedCallback?.Invoke(); * break;*/ case SocketCommands.ReturnClientIDAfterAccept: myLogger.Log("Starting new CLIENT connection with ID: {0}", sm.id); Id = sm.id; break; case SocketCommands.CloseInstance: myLogger.Log("Client is closing connection..."); Stop(false); break; default: myLogger.Log("Unknown ClientCallbackion to take! Case: {0}", cmd.Command); break; } } else { myLogger.Log("Empty string received by client!"); } } else { ReceivedServerMessageCallback?.Invoke(sm.msg, argContainer); } }
private void HandleAction(SocketMessage sm, SocketContainer argContainer) { //string val = sm.StringValue; if (sm.msg is SocketCommand) { SocketCommand cmd = sm.msg.CastType <SocketCommand>(); if (cmd != null) { switch (cmd.Command) { case SocketCommands.CloseClients: CloseAllClients(sm.id); break; case SocketCommands.ClosedClient: //closedClients.Add(sm.id); SocketManager.PoliteClose(sm.id); //Tell to the client that it has been disconnected from it routingTable.Remove(sm.id); CloseServerAfterClientsClose(dispose); break; case SocketCommands.Stop: CloseAllClients(sm.id); break; case SocketCommands.UnpoliteStop: object d = cmd.Metadata["Dispose"]; Stop(d != null && ((bool)d)); break; default: DoServerError(string.Format("Cannot de-encrypt the message! Unrecognized 'enum' case: {0}", cmd.Command), sm.id); break; } } } else { //If not is a command, then send the object to other clients... SendToClient(sm, sm.DestsId); } }
public void ParseReceivedClientMessage(object obj, SocketContainer argContainer) { //Aquí ocurre la magia if (obj is string) { string argCommandString = (string)obj; myLogger.Log(""); //myLogger.Log("ParseReceivedClientMessage: " + argCommandString); // parse the command string string argCommand = null; string argText = null; if (argCommandString.StartsWith("/")) { argCommand = argCommandString.Substring(0, argCommandString.IndexOf(" ")); argText = argCommandString.Remove(0, argCommand.Length + 1); } else { argText = argCommandString; } switch (argText) { case "hi server": SendMessageToClient("/say Server replied.", argContainer); break; } MessageReceived?.Invoke(argCommandString, argContainer); } else if (obj is SocketMessage) { HandleAction((SocketMessage)obj, argContainer); } //This is a server-only method, that is called for "Debugging purpouses" by the moment ReceivedClientMessageCallback?.Invoke(obj, argContainer); //Check there in case of ((SocketMessage)obj).DestsId[0] == 0?? }
public void MessagePartSent(IAsyncResult ar) { // get the async state object which was returned by the async beginsend method //AsyncSendState mState = (AsyncSendState)ar.AsyncState; SocketContainer co = ar.AsyncState.CastType <SocketContainer>(); try { int numBytesSent = 0; // call the EndSend method which will succeed or throw an error depending on if we are still connected numBytesSent = co.Socket.EndSend(ar); // increment the total amount of bytes processed so far co.sState.Progress += numBytesSent; // determine if we havent' sent all the data for this Packet yet if (co.sState.NextLength() > 0) { // we need to send more data co.Socket.BeginSend(co.sState.BytesToSend, co.sState.NextOffset(), co.sState.NextLength(), SocketFlags.None, new AsyncCallback(MessagePartSent), co); } else { Console.WriteLine("Client MessagePartSent completed. Clearing stuff..."); //Reset for the next time Array.Clear(co.sState.BytesToSend, 0, co.sState.BytesToSend.Length); Array.Resize(ref co.sState.BytesToSend, gBufferSize); } // at this point, the EndSend succeeded and we are ready to send something else! // TODO: use the queue to determine what message was sent and show it in the local chat buffer //RaiseEvent MessageSentToServer() } catch (Exception ex) { myLogger.Log("DataSent error: " + ex.Message); } }
/// <summary> /// QueueMessage prepares a Message object containing our data to send and queues this Message object in the OutboundMessageQueue. /// </summary> /// <remarks></remarks> public void SendToClient(object obj, SocketContainer co) { // serialize the Packet into a stream of bytes which is suitable for sending with the Socket BinaryFormatter mSerializer = new BinaryFormatter(); using (MemoryStream mSerializerStream = new MemoryStream()) { mSerializer.Serialize(mSerializerStream, obj); // get the serialized Packet bytes byte[] mPacketBytes = mSerializerStream.GetBuffer(); // convert the size into a byte array byte[] mSizeBytes = BitConverter.GetBytes(mPacketBytes.Length + 4); // create the async state object which we can pass between async methods //AsyncSendState mState = new AsyncSendState(argClient); // resize the BytesToSend array to fit both the mSizeBytes and the mPacketBytes // TODO: ReDim mState.BytesToSend(mPacketBytes.Length + mSizeBytes.Length - 1) Array.Resize(ref co.sState.BytesToSend, mPacketBytes.Length + mSizeBytes.Length); // copy the mSizeBytes and mPacketBytes to the BytesToSend array Buffer.BlockCopy(mSizeBytes, 0, co.sState.BytesToSend, 0, mSizeBytes.Length); Buffer.BlockCopy(mPacketBytes, 0, co.sState.BytesToSend, mSizeBytes.Length, mPacketBytes.Length); Array.Clear(mSizeBytes, 0, mSizeBytes.Length); Array.Clear(mPacketBytes, 0, mPacketBytes.Length); Console.Write(""); // queue the Message Console.WriteLine("Server (SendToClient): NextOffset: {0}; NextLength: {1}", co.sState.NextOffset(), co.sState.NextLength()); co.Socket.BeginSend(co.sState.BytesToSend, co.sState.NextOffset(), co.sState.NextLength(), SocketFlags.None, new AsyncCallback(MessagePartSent), co); } }
private void ClientDisconnected(SocketContainer co) { listBox1.Items.Remove(co.Socket.RemoteEndPoint); }
public void SendMessageToServer(string argCommandString, SocketContainer container) { Send(argCommandString, container); }
/// <summary> /// BeginReceiveCallback is an async callback method that gets called when the server receives some data from a client socket after calling the async BeginReceive method. /// </summary> /// <param name="ar"></param> /// <remarks></remarks> public void ClientMessageReceived(IAsyncResult ar) { // get the async state object from the async BeginReceive method //AsyncReceiveState mState = (AsyncReceiveState)ar.AsyncState; SocketContainer co = ar.AsyncState.CastType <SocketContainer>(); // call EndReceive which will give us the number of bytes received int numBytesReceived = 0; try { numBytesReceived = co.Socket.EndReceive(ar); } catch (SocketException ex) { // if we get a ConnectionReset exception, it could indicate that the client has disconnected if (ex.SocketErrorCode == SocketError.ConnectionReset) { ClientDisconnected?.Invoke(co); return; } } // if we get numBytesReceived equal to zero, it could indicate that the client has disconnected if (numBytesReceived == 0) { ClientDisconnected?.Invoke(co); return; } // determine if this is the first data received if (co.rState.ReceiveSize == 0) { // this is the first data recieved, so parse the receive size which is encoded in the first four bytes of the buffer co.rState.ReceiveSize = BitConverter.ToInt32(co.rState.Buffer, 0); // write the received bytes thus far to the packet data stream co.rState.PacketBufferStream.Write(co.rState.Buffer, 4, numBytesReceived - 4); } else { // write the received bytes thus far to the packet data stream co.rState.PacketBufferStream.Write(co.rState.Buffer, 0, numBytesReceived); } // increment the total bytes received so far on the state object co.rState.TotalBytesReceived += numBytesReceived; // check for the end of the packet // bytesReceived = Carcassonne.Library.PacketBufferSize Then if (co.rState.TotalBytesReceived < co.rState.ReceiveSize) { //File.AppendAllText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "serverAppend.txt"), string.Join(" ", co.rState.Buffer.Select(x => x.ToString())) + " "); // ## STILL MORE DATA FOR THIS PACKET, CONTINUE RECEIVING ## // the TotalBytesReceived is less than the ReceiveSize so we need to continue receiving more data for this packet co.Socket.BeginReceive(co.rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ClientMessageReceived), co); } else { // ## FINAL DATA RECEIVED, PARSE AND PROCESS THE PACKET ## // the TotalBytesReceived is equal to the ReceiveSize, so we are done receiving this Packet...parse it! BinaryFormatter mSerializer = new BinaryFormatter(); // rewind the PacketBufferStream so we can de-serialize it co.rState.PacketBufferStream.Position = 0; // de-serialize the PacketBufferStream which will give us an actual Packet object co.rState.Packet = mSerializer.Deserialize(co.rState.PacketBufferStream); Console.WriteLine("Succesfully deserialized object of type: {0}", co.rState.Packet.GetType().Name); // handle the message ParseReceivedClientMessage(co.rState.Packet, co); // call BeginReceive again, so we can start receiving another packet from this client socket //AsyncReceiveState mNextState = new AsyncReceiveState(); //mNextState.Socket = mState.Socket; // ??? Console.WriteLine("Server ClientMessageReceived => CompletedSynchronously: {0}; IsCompleted: {1}", ar.CompletedSynchronously, ar.IsCompleted); co.Socket.BeginReceive(co.rState.Buffer, 0, gBufferSize, SocketFlags.None, new AsyncCallback(ClientMessageReceived), co); //Dispose of everything we dont need after receive message from client Array.Clear(co.rState.Buffer, 0, co.rState.Buffer.Length); co.rState.ReceiveSize = 0; co.rState.Packet = null; co.rState.TotalBytesReceived = 0; co.rState.PacketBufferStream.Close(); co.rState.PacketBufferStream.Dispose(); co.rState.PacketBufferStream = new MemoryStream(); } }
/// <summary> /// QueueMessage prepares a Message object containing our data to send and queues this Message object in the OutboundMessageQueue. /// </summary> /// <remarks></remarks> public void SendMessageToClient(string argCommandString, SocketContainer argContainer) { SendToClient(argCommandString, argContainer); }
private static void server_MessageReceived(string argMessage, SocketContainer argContainer) { Console.WriteLine("Received message of {0} bytes length.", argMessage.Length); }
private void server_ClientDisconnected(SocketContainer argContainer) { Invoke(new ClientDisconnectedDelegate(ClientDisconnected), argContainer); }
private void server_MessageReceived(string argMessage, SocketContainer argContainer) { Invoke(new MessageReceivedDelegate(MessageReceived), new object[] { argMessage, argContainer }); }
public void Add(SocketContainer argContainer) { Messages.Enqueue(argContainer); MessageQueued?.Invoke(); }