public void StartListening(string IP, int port, Boolean test) { // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". IPHostEntry ipHostInfo = Dns.GetHostEntry(IP); //Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; //IPAddress local = IPAddress.Parse(IP); UInt16 sendCRC = 0; DateTime date; int year = 0; int month = 0; int day = 0; int hour = 0; int minute = 0; int second = 0; IPEndPoint localEndPoint = null; if (test) { localEndPoint = new IPEndPoint(IPAddress.Any, port); } else { localEndPoint = new IPEndPoint(ipAddress, port); } // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { allDone.Reset(); listener.Bind(localEndPoint); listener.Listen(100); //login code, wait for 1st message Console.WriteLine("Wait 5 seconds for login message"); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); Boolean firstMessage = true; //loop forever while (true) { allDone.WaitOne(); //read fifo until empty while (fifo.Count > 0) { //read one connection until buffer doesn't contain any more packets KeyValuePair <List <byte>, StateObject> byteState = ReadWrite(-1, PROCESS_STATE.PROCESS, null, null, null); StateObject state = byteState.Value; while (true) { KeyValuePair <UNPACK_STATUS, byte[]> status = Unpack(byteState.Key); if (status.Key == UNPACK_STATUS.NOT_ENOUGH_BYTES) { break; } //message is 2 start bytes + 1 byte (message length) + 1 byte message length + 2 end bytes byte[] receiveMessage = status.Value; if (status.Key != UNPACK_STATUS.GOOD_MESSAGE) { int zzz = -1; } int messageLength = receiveMessage[2]; Console.WriteLine("Status : '{0}', Receive Message : '{1}'", status.Key == UNPACK_STATUS.GOOD_MESSAGE ? "Good" : "Bad", BytesToString(receiveMessage.Take(messageLength + 5).ToArray())); if (status.Key != UNPACK_STATUS.GOOD_MESSAGE) { Console.WriteLine("Error : Bad Login Message, Data : '{0}'", BytesToString(receiveMessage)); break; } else { if (firstMessage) { if (receiveMessage[3] != 0x01) { Console.WriteLine("Error : Expected Login Message : '{0}'", BytesToString(receiveMessage)); break; } firstMessage = false; } //skip start bytes, message length. then go back 4 bytes (CRC and serial number) byte[] serialNumber = receiveMessage.Skip(2 + 1 + messageLength - 4).Take(2).ToArray(); PROTOCOL_NUMBER protocolNumber = (PROTOCOL_NUMBER)receiveMessage[3]; switch (protocolNumber) { case PROTOCOL_NUMBER.LOGIN_MESSAGE: serialNumber.CopyTo(loginResponse, 4); sendCRC = crc_bytes(loginResponse.Skip(2).Take(loginResponse.Length - 6).ToArray()); loginResponse[loginResponse.Length - 4] = (byte)((sendCRC >> 8) & 0xFF); loginResponse[loginResponse.Length - 3] = (byte)((sendCRC) & 0xFF); string terminalID = Encoding.ASCII.GetString(receiveMessage.Skip(4).Take(messageLength - 5).ToArray()); Console.WriteLine("Received good login message from Serial Number : '{0}', Terminal ID = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), terminalID); Console.WriteLine("Send Message : '{0}'", BytesToString(loginResponse)); Send(state.workSocket, loginResponse); break; case PROTOCOL_NUMBER.LOCATION_DATA: year = receiveMessage[4]; month = receiveMessage[5]; day = receiveMessage[6]; hour = receiveMessage[7]; minute = receiveMessage[8]; second = receiveMessage[9]; date = new DateTime(2000 + year, month, day, hour, minute, second); Console.WriteLine("Received good location message from Serial Number '{0}', Time = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), date.ToLongDateString()); break; case PROTOCOL_NUMBER.ALARM_DATA: year = receiveMessage[4]; month = receiveMessage[5]; day = receiveMessage[6]; hour = receiveMessage[7]; minute = receiveMessage[8]; second = receiveMessage[9]; date = new DateTime(2000 + year, month, day, hour, minute, second); Console.WriteLine("Received good alarm message from Serial Number '{0}', Time = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), date.ToLongDateString()); int packetLen = alarmResponse.Length - 5; alarmResponse[2] = (byte)(packetLen & 0xFF); serialNumber.CopyTo(alarmResponse, packetLen - 1); sendCRC = crc_bytes(alarmResponse.Skip(2).Take(packetLen - 1).ToArray()); alarmResponse[packetLen + 1] = (byte)((sendCRC >> 8) & 0xFF); alarmResponse[packetLen + 2] = (byte)((sendCRC) & 0xFF); Console.WriteLine("Send Message : '{0}'", BytesToString(alarmResponse)); Send(state.workSocket, alarmResponse); break; } //end switch } // End if } //end while } //end while fifo > 0 allDone.Reset(); } //end while true } catch (Exception e) { Console.WriteLine(e.Message); } }
static KeyValuePair <List <byte>, StateObject> ReadWrite(long connectionNumber, PROCESS_STATE ps, Socket handler, IAsyncResult ar, List <byte> working_buffer) { KeyValuePair <List <byte>, StateObject> byteState = new KeyValuePair <List <byte>, StateObject>();; StateObject state = null; Object thisLock = new Object(); lock (thisLock) { switch (ps) { case PROCESS_STATE.ACCEPT: state = new StateObject(); state.buffer = new byte[BUFFER_SIZE]; state.connectionNumber = connectionNumber; connectionDict.Add(connectionNumber++, new KeyValuePair <List <byte>, StateObject>(new List <byte>(), state)); // Create the state object. state.workSocket = handler; byteState = new KeyValuePair <List <byte>, StateObject>(null, state); break; case PROCESS_STATE.READ: //catch when client disconnects try { // Read data from the client socket. int bytesReads = handler.EndReceive(ar); if (bytesReads > 0) { byteState = connectionDict[connectionNumber]; byteState.Key.AddRange(byteState.Value.buffer.Take(bytesReads).ToArray()); } //only put one instance of connection number into fifo if (!fifo.Contains(connectionNumber)) { fifo.Add(connectionNumber); } } catch (Exception ex) { fifo.RemoveAll(x => x == connectionNumber); connectionDict.Remove(connectionNumber); byteState = new KeyValuePair <List <byte>, StateObject>(); } break; case PROCESS_STATE.PROCESS: if (fifo.Count > 0) { byteState = connectionDict[fifo.First()]; fifo.RemoveAt(0); byteState.Key.AddRange(byteState.Key); } break; case PROCESS_STATE.UNPACK: int len = working_buffer[2]; if ((working_buffer[0] != 0x78) && (working_buffer[1] != 0x78) && (working_buffer[len + 3] != 0x0D) && (working_buffer[len + 4] != 0x0A)) { working_buffer.Clear(); return(new KeyValuePair <List <byte>, StateObject>(null, null)); } List <byte> packet = working_buffer.Take(len + 5).ToList(); working_buffer.RemoveRange(0, len + 5); byteState = new KeyValuePair <List <byte>, StateObject>(packet, null); break; } // end switch } return(byteState); }