· 5 years ago · Apr 23, 2020, 01:16 PM
1/**
2 * This in codetemplate for SpedeSgames server.
3 * There is examples for file based and database based
4 * records saving.
5 */
6using System;
7using System.Collections.Generic;
8using System.Linq;
9using System.Text;
10using System.Threading.Tasks;
11using System.Threading;
12
13using System.IO;
14
15using System.Net;
16using System.Net.Sockets;
17
18using System.Data.SqlClient; // SQL Server
19using System.Data;
20
21namespace SpedeSgamesServer
22{
23 /**
24 * class for Server's Main method
25 */
26 class Program
27 {
28 //Main method should be public and async
29 public static async Task Main(string[] args)
30 {
31 // create Server object
32 Server server = new Server();
33
34 // call Listen task asyncronously and wait it's end
35 await server.Listen();
36 }
37 }
38 /**
39 * class for handling SpedeSgames's results
40 *
41 * There is also an example for Sql database connection
42 */
43 class Server
44 {
45 // attributes
46 TcpListener listener; // Listener object
47 protected bool go = true; // flag for listening loop
48 string fname; // file name for results
49
50 // for database handlind (Sql Server)
51 SqlConnection sql; // for connection handlind
52 SqlCommand cmd; // for sql commands executing
53
54 // constructor
55 public Server(string fname = "records.txt", int port = 12345)
56 {
57 listener = new TcpListener(IPAddress.Any, port);
58 this.fname = fname;
59
60 //Console.WriteLine($"{DateTime.Now}Server started");
61 try // for error handling
62 {
63 // open connection to MySql server
64 sql = new SqlConnection(
65 @"Server=tcp:ds20-dbserver.database.windows.net,1433;
66 Initial Catalog=ds20_db;User ID=turutimo;Password=Koodaus1;
67 Connection Timeout=30");
68 sql.Open();
69 //Console.WriteLine($"{DateTime.Now}: Connected to database!");
70
71 // create the records table
72 // this generates an exeption if the table exists
73 cmd = new SqlCommand( // table creation statement
74 @"create table ds20_records_miikka (
75 name varchar(20),
76 time varchar(20),
77 result decimal(5,2) not null,
78 target decimal(5,2) not null,
79 primary key (name, time)
80 )", sql);
81 cmd.ExecuteNonQuery(); // execute table creation statement
82 }
83 catch (Exception ex)
84 { // if an error exists
85 // handle the exception if necessary
86 //Console.WriteLine(ex);
87 }
88 }
89 // listening loop task
90 public async Task Listen()
91 {
92 List<Task> tasks = new List<Task>(); // for task infos
93 TcpClient client; // for connection handling from accept
94 listener.Start(); // start listening
95 try
96 {
97 // listening loop while go flag is true
98 while (go)
99 {
100 client = await listener.AcceptTcpClientAsync();
101 // create task for connection
102 tasks.Add(HandleConnection(client));
103 tasks.RemoveAll(x => x.IsCompleted);
104 tasks.RemoveAll(x => x.IsCanceled);
105 // how to remove stopped tasks from list
106 }
107 }
108 catch (Exception ex)
109 {
110 // this exception based loop ending works
111 // in Windows but not on bott's mono environment
112 Console.WriteLine(ex);
113 }
114 listener.Stop();
115 // can we wait until all tasks have stopped
116 }
117 // task for communicating
118 protected async Task HandleConnection(TcpClient client)
119 {
120 StreamReader rdr = new StreamReader(client.GetStream()); // get the reader stream
121 StreamWriter wtr = new StreamWriter(client.GetStream()); // writer
122 string msg; // message buffer for reading
123 // message handling loop
124 do
125 {
126 // read message from client's stream
127 msg = rdr.ReadLine();
128 //Console.WriteLine(msg);
129 // handle not empty messages - an empty message ends communication
130 if (msg != "")
131 {
132 // message format like:
133 // '<cmd>: <command parameters>'
134 // cmds: res - save record
135 // rec <top> - get top records
136 // stop - stop server listening and executing
137
138 // split the message for getting
139 // command and parameters
140 string[] parts = msg.Split(new string[] { ": ", ", " }, StringSplitOptions.None);
141 // handle commands
142 switch (parts[0])
143 {
144 // records from the database
145 case "rec":
146 // add here your own code for records getting
147 try
148 {
149 wtr.WriteLine($"rec: {parts[1]}\r\n");
150 wtr.Flush();
151
152 SqlDataReader reader;
153
154
155 cmd.CommandText = String.Format(new System.Globalization.CultureInfo("en-US"),
156 $"select top {parts[1]} * from ds20_records_miikka order by abs (result)");
157 cmd.ExecuteNonQuery();
158
159 reader = cmd.ExecuteReader(); // execute
160 string content = "";
161 while (reader.Read())
162 {
163 //Console.WriteLine(String.Format("{0}, {2}, {3}, {1}", reader[0], reader[1], reader[2], reader[3]));
164 content +=
165 reader["name"].ToString() + ", " +
166 reader["result"].ToString() + ", " +
167 reader["target"].ToString() + ", " +
168 reader["time"].ToString() + "/";
169 }
170 reader.Close();
171 Console.WriteLine(content);
172 wtr.WriteLine(content);
173 wtr.Flush();
174
175 }
176 catch (Exception ex)
177 {
178 Console.WriteLine(ex.Message);
179 }
180
181 break;
182 // results from the client
183 case "res":
184 // we need to save the results to the database table
185 try
186 {
187 // insert statement definition
188 cmd.CommandText = String.Format(new System.Globalization.CultureInfo("en-US"),
189 "insert into ds20_records_miikka values " +
190 "('{0}', '{1}', {2:0.00}, {3:0.00})",
191 parts[1], parts[4], double.Parse(parts[2]), double.Parse(parts[3]));
192 cmd.ExecuteNonQuery(); // execute the insertion
193 }
194 catch (Exception ex)
195 {
196 Console.WriteLine(ex.Message);
197 }
198
199 // write to the result file
200 File.AppendAllText(fname, $"{msg}\r\n");
201 break;
202 // stop the listener loop
203 case "stop":
204 go = false; // seg go flag to be false for stopping
205 sql.Close();
206 listener.Stop(); // throw an exception for accept
207
208 // send empty message to listener for stopping
209 // using temporary connection object
210 TcpClient cclient = new TcpClient("localhost", 12345);
211 StreamWriter cwtr = new StreamWriter(cclient.GetStream());
212 cwtr.WriteLine(); cwtr.Flush();
213 cclient.Close(); // close temporary connection object
214 break;
215 case "delete":
216
217 Console.WriteLine("Deleted");
218 cmd.CommandText = String.Format(new System.Globalization.CultureInfo("en-US"), "TRUNCATE TABLE ds20_records_miikka");
219 cmd.ExecuteNonQuery();
220 break;
221 }
222 }
223 } while (msg != ""); // until the empty msg
224
225 client.Close(); // close task's connection object
226
227 }
228 }
229}