· 5 years ago · Apr 23, 2020, 11:12 AM
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_turutimo (
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 // start waiting connections
98 client = await listener.AcceptTcpClientAsync();
99 // listening loop while go flag is true
100 while (go)
101 {
102
103
104 // create task for connection
105 tasks.Add(HandleConnection(client));
106
107 // how to remove stopped tasks from list
108 }
109 }
110 catch (Exception ex)
111 {
112 // this exception based loop ending works
113 // in Windows but not on bott's mono environment
114 }
115 listener.Stop();
116 // can we wait until all tasks have stopped
117 }
118 // task for communicating
119 protected async Task HandleConnection(TcpClient client)
120 {
121 StreamReader rdr = new StreamReader(client.GetStream()); // get the reader stream
122 StreamWriter wtr = new StreamWriter(client.GetStream()); // writer
123 string msg; // message buffer for reading
124 // message handling loop
125 do
126 {
127 // read message from client's stream
128 msg = rdr.ReadLine();
129 Console.WriteLine(msg);
130 // handle not empty messages - an empty message ends communication
131 if (msg != "")
132 {
133 // message format like:
134 // '<cmd>: <command parameters>'
135 // cmds: res - save record
136 // rec <top> - get top records
137 // stop - stop server listening and executing
138
139 // split the message for getting
140 // command and parameters
141 string[] parts = msg.Split(new string[] { ": ", ", " }, StringSplitOptions.None);
142 // handle commands
143 switch (parts[0])
144 {
145 // records from the database
146 case "rec":
147 // add here your own code for records getting
148 try
149 {
150 SqlDataReader reader;
151 // insert statement definition
152 cmd.CommandText = String.Format(new System.Globalization.CultureInfo("en-US"),
153 $"select top {parts[1]} * from ds20_records_turutimo order by time desc ");
154 reader = cmd.ExecuteReader(); // execute
155 msg = "";
156 while (reader.Read())
157 {
158 //Console.WriteLine(String.Format("{0}, {2}, {3}, {1}", reader[0], reader[1], reader[2], reader[3]));
159 msg = msg + (String.Format("{0}, {2}, {3}, {1}", reader[0], reader[1], reader[2], reader[3])) + "/";
160 }
161
162 wtr.WriteLine(msg);
163 wtr.Flush();
164
165 reader.Close();
166 }
167 catch (Exception ex)
168 {
169 Console.WriteLine(ex.Message);
170 }
171
172 break;
173 // results from the client
174 case "res":
175 // we need to save the results to the database table
176 try
177 {
178 // insert statement definition
179 cmd.CommandText = String.Format(new System.Globalization.CultureInfo("en-US"),
180 "insert into ds20_records_turutimo values " +
181 "('{0}', '{1}', {2:0.00}, {3:0.00})",
182 parts[1], parts[4], double.Parse(parts[2]), double.Parse(parts[3]));
183 cmd.ExecuteNonQuery(); // execute the insertion
184 }
185 catch (Exception ex)
186 {
187 Console.WriteLine(ex.Message);
188 }
189
190 // write to the result file
191 File.AppendAllText(fname, $"{msg}\r\n");
192 break;
193 // stop the listener loop
194 case "stop":
195 go = false; // seg go flag to be false for stopping
196 listener.Stop(); // throw an exception for accept
197
198 // send empty message to listener for stopping
199 // using temporary connection object
200 TcpClient cclient = new TcpClient("localhost", 12345);
201 StreamWriter cwtr = new StreamWriter(cclient.GetStream());
202 cwtr.WriteLine(); cwtr.Flush();
203 cclient.Close(); // close temporary connection object
204 break;
205 }
206 }
207 } while (msg != ""); // until the empty msg
208
209 client.Close(); // close task's connection object
210 }
211 }
212}