using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.Windows.Forms; using System.IO; using System.Xml.Serialization; namespace ITransfer { public class SocketServer { //Database //Singleton pattern database to write all incoming objects to the DB. public static Database db = Database.Instance; // Thread signal. // Triggers the main thread to continue (listening for clients) // when the previous incoming connection request has been handled. public static ManualResetEvent allDone = new ManualResetEvent(false); //Constructor public SocketServer() { db.Connect(); } //Listens for a new connection on the main thread. public static void ListenNewConnection() { // Data buffer for incoming data. byte[] bytes = new Byte[1024]; #region Create Listener Socket // Establish the local endpoint for the socket. // The DNS name of the computer IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); #endregion // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. /*Console.WriteLine("Waiting for a connection...");*/ listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing. allDone.WaitOne(); } } catch (Exception e) { MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } } //Creates a new socket for the incoming connection of the main thread. public static void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. StateObject state = new StateObject(); state.OperationState = "INI"; state.workSocket = handler; Send(state.workSocket, "HI"); handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } //Receives data from a certain socket. public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; int bytesRead; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; switch(state.OperationState) { #region INI case "INI": //SENDED "HI" TO THE CLIENT //EXPECTING "HI" AS RETURN bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { state.sb.Append(Encoding.ASCII.GetString( state.buffer, 0, bytesRead)); string clientReply = state.sb.ToString(); if (clientReply == "HI") { //A proper connection has been made. //Request the number of files to receive. state.sb.Remove(0, state.sb.Length); state.OperationState = "NUM_FILE_REQUEST"; Send(handler, "NF"); handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } break; #endregion #region NUM_FILE_REQUEST case "NUM_FILE_REQUEST": //SENDED "NF" TO THE CLIENT //EXPECTING INT AS RETURN bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { state.sb.Append(Encoding.ASCII.GetString( state.buffer, 0, bytesRead)); string clientReply = state.sb.ToString(); int numFiles = int.Parse(clientReply); if (numFiles > 0) { //There are files that need to be sent. //Request the transfer. state.sb.Remove(0, state.sb.Length); state.NumberOfFiles = numFiles; state.OperationState = "SEND_FILESIZE"; Send(handler, "SF"); handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } else { //else there are no files to be received. close the connection. handler.Shutdown(SocketShutdown.Both); handler.Close(); } } break; #endregion #region SEND_FILESIZE case "SEND_FILESIZE": //SENDED 'SF' TO THE CLIENT //EXPECTING FILESIZE AS RETURN bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { //Get the fileSize state.sb.Append(Encoding.ASCII.GetString( state.buffer, 0, bytesRead)); string clientReply = state.sb.ToString(); long fileSize = long.Parse(clientReply); //set the filesize in the state state.currentFileSize = fileSize; //clear the string in the state state.sb.Remove(0, state.sb.Length); //Set the state to GO FILE state.OperationState = "GO_FILE"; Send(handler, "GF"); //Start receiving the file handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } break; #endregion #region GO_FILE case "GO_FILE": //SENDED 'GF' TO THE CLIENT //EXPECTING FILE AS RETURN bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { state.memstream.Write(state.buffer, 0, bytesRead); //file is complete if (state.memstream.Length >= state.currentFileSize) { XmlSerializer xs = new XmlSerializer(typeof(KioskInfo)); state.memstream.Seek(0, SeekOrigin.Begin); KioskInfo s = (KioskInfo)xs.Deserialize(state.memstream); //HERE IS WHERE THE FILE HANDLING OCCURS //WRITING TO FILE //WRITING TO DATABASE etc. db.addEntry(s.NaamPC, s.Datum, s.Uur); //MessageBox.Show(s.NaamPC); /* FileStream fs = new FileStream("Test.txt", FileMode.Create); BinaryWriter w = new BinaryWriter(fs); w.Write(state.memstream.ToArray(),0,state.memstream.ToArray().Length); w.Close(); fs.Close(); */ state.memstream.Flush(); state.memstream.Close(); state.memstream = new MemoryStream(); Send(handler, "NX"); state.NumberOfFiles--; //if there are more files, receive the next filesize otherwise //close the socket if (state.NumberOfFiles == 0) { handler.Shutdown(SocketShutdown.Both); handler.Close(); } else { state.OperationState = "SEND_FILESIZE"; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } //file isn't complete yet else { //CONTINUE LISTENING FOR DATA handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } break; #endregion } } //Start sending data to a certain socket. private static void Send(Socket handler, String data) { // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } //ending the send to a certain socket. private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); //handler.Shutdown(SocketShutdown.Both); //handler.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } } }