source: trunk/CrypPlugins/KeySearcher/Server/Server.cs @ 2411

Last change on this file since 2411 was 2411, checked in by schwittmann, 11 years ago

Shutdown external client server gracefully

File size: 5.3 KB
Line 
1using System;
2using System.Text;
3using System.Net.Sockets;
4using System.Threading;
5using System.Net;
6using System.Collections.Generic;
7
8class CryptoolServer
9{
10    public int Port {get;set;}
11   
12    public delegate void JobCompletedDelegate(EndPoint ipep, JobResult j);
13    public event JobCompletedDelegate OnJobCompleted;
14
15
16    public delegate void ClientConnectedDelegate(EndPoint ipep, String identification);
17    public event ClientConnectedDelegate OnClientConnected;
18
19    public delegate void ClientDisconnectedDelegate(EndPoint ipep);
20    public event ClientDisconnectedDelegate OnClientDisconnected;
21
22    private Dictionary<EndPoint, TcpClient> connectedClients = new Dictionary<EndPoint, TcpClient>();
23    private TcpListener tcpListener;
24    private bool running = false;
25
26    ///<summary>
27    /// Starts the server. Will block as long as the server runs, you might want to start this in an additional thread.
28    ///</summary>
29    public void Run()
30    {
31        lock (this)
32        {
33            if (running)
34            {
35                throw new Exception("Invalid state: Already running");
36            }
37            running = true;
38        }
39
40        try
41        {
42            tcpListener = new TcpListener(IPAddress.Any, Port);
43            tcpListener.Start();
44            Console.WriteLine("Listening for client on port " + Port);
45            while (running)
46            {
47                TcpClient client = tcpListener.AcceptTcpClient();
48                Console.WriteLine("Got connection from " + client);
49                lock (connectedClients)
50                {
51                    connectedClients.Add(client.Client.RemoteEndPoint, client);
52                }
53                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
54                clientThread.Start(client);
55            }
56        }
57        catch (ThreadInterruptedException)
58        {
59        }
60        catch (SocketException e)
61        {
62            if (running)
63            {
64                Console.WriteLine("CryptoolServer: Got SocketException while running");
65            }
66        }
67
68
69        tcpListener.Stop();
70        foreach(var client in connectedClients)
71            client.Value.Close();
72    }
73   
74    public void SendJob(JobInput j, EndPoint i)
75    {
76        TcpClient client = null;
77        lock(connectedClients)
78        {
79            if(!connectedClients.TryGetValue(i, out client))
80                throw new ArgumentException("Not connected to "+i);
81        }
82
83        lock(client)
84        {
85            var wrapped = new PlatformIndependentWrapper(client);
86
87            wrapped.WriteInt((int)ServerOpcodes.NEW_JOB);
88            wrapped.WriteString(j.Guid);
89            wrapped.WriteString(j.Src);
90            wrapped.WriteInt(j.Key.Length);
91            wrapped.WriteBytes(j.Key);
92            wrapped.WriteInt(j.LargerThen ? 1 : 0);
93            wrapped.WriteInt(j.Size);
94            wrapped.WriteInt(j.ResultSize);
95        }
96    }
97
98    private void HandleClient(object obj)
99    {
100        var client = obj as TcpClient;
101        EndPoint ep = client.Client.RemoteEndPoint;
102
103        try
104        {
105            var wrapped = new PlatformIndependentWrapper(client);
106            while(true)
107            {
108                switch((ClientOpcodes)wrapped.ReadInt())
109                {
110                    case ClientOpcodes.HELLO:
111                        {
112                            String identification = wrapped.ReadString();
113                            if(OnClientConnected != null)
114                                OnClientConnected(ep, identification);
115                        }
116                        break;
117
118                    case ClientOpcodes.JOB_RESULT:
119                        {
120                            var jobGuid = wrapped.ReadString();
121                            var resultList = new List<KeyValuePair<float, int>>();
122                            var resultListLength = wrapped.ReadInt();
123                            for (int c = 0; c < resultListLength; c++)
124                            {
125                                var key = wrapped.ReadInt();
126                                var cost = wrapped.ReadFloat();
127                                resultList.Add(new KeyValuePair<float, int>(cost, key));
128                            }
129
130                            JobResult rs = new JobResult();
131                            rs.Guid = jobGuid;
132                            rs.ResultList = resultList;
133
134                            if(OnJobCompleted != null)
135                            {
136                                OnJobCompleted(ep, rs);
137                            }
138                        }
139                        break;
140                }
141            }
142        }
143        catch(Exception e)
144        {
145            Console.WriteLine("Client exited with exception "+e);
146        }
147
148        lock(connectedClients)
149        {
150            connectedClients.Remove(ep);
151        }
152
153        if(OnClientDisconnected != null)
154            OnClientDisconnected(ep);
155    }
156
157    /// <summary>
158    /// Closes this server. Any concurrent call to Run() in any other thread will return.
159    /// </summary>
160    public void Shutdown()
161    {
162        lock (this)
163        {
164            running = false;
165            tcpListener.Stop();
166        }
167    }
168}
Note: See TracBrowser for help on using the repository browser.