- using System;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Collections;
- using System.Threading;
- using System.Linq;
- public class UdpSrvrSample
- {
- private static int game_state = 0;//0-gra czeka na rozpoczecie 1- gra skonczona;
- private static int connected_hosts = 0;//licznik hostow
- private static int times_up = 0;//0-nie minelo jeszcze 10s
- private static Random random = new Random();
- public static int sekretna = random.Next(0, 15);
- public static int time2;
- public static void Timer(string h2,string h1)
- {
- int id1 = Convert.ToInt32(h1, 2);
- int id2 = Convert.ToInt32(h2, 2);
- time2 = (((id1 + id2) * 99) % 100) + 30;
- while(time2!=0)
- {
- if (time2 >= 10)
- {
- Thread.Sleep(10000);
- time2 = time2 - 10;
- }
- else
- {
- Thread.Sleep(time2 * 1000);
- time2 = 0;
- game_state++;//timeout
- }
- times_up++;
- }
- }
- static byte [] ProtocolBuilder(string operation,string response,string idref,string dop="none")//buduje pakiet
- {
- int pom1 = 0, pom2 = 0, pom3 = 0, pom4 = 0;
- BitArray c = new BitArray(24);
- BitArray g = new BitArray(24);
- byte[] data = new byte[3];
- for (int i=0;i<c.Length;i++)
- {
- if(i<=5)
- {
- if (operation[pom1] == '0')
- c[i] = false;
- else
- c[i] = true;
- pom1++;
- }
- if(i>5 && i<=9)
- {
- if (response[pom2] == '0')
- c[i] = false;
- else
- c[i] = true;
- pom2++;
- }
- if(i>9 && i<=17)
- {
- if (idref[pom3] == '0')
- c[i] = false;
- else
- c[i] = true;
- pom3++;
- }
- if (i > 17)
- {
- if(dop=="none")
- c[i] = false;
- else
- {
- if (dop[pom4] == '0')
- c[i] = false;
- else
- c[i] = true;
- pom4++;
- }
- }
- }
- for (int i = 0; i < c.Length; i++)
- {
- g[g.Length - i-1] = c[i];
- }
- g.CopyTo(data, 0);
- Array.Reverse(data, 0, data.Length);
- return data;
- }
- public static string ToBin(int value, int len)//int do binarki
- {
- return (len > 1 ? ToBin(value >> 1, len - 1) : null) + "01"[value & 1];
- }
- public static string[] DecodePacket(byte[] c)//funkcja odbiera pobrane inty i zamienia je na kod binarny
- {
- string h = "";
- string [] a=new string[3];
- for (int i = 0; i < c.Length;i++)
- {
- h=h+ ToBin(c[i], 8);//dopelnia do 8 bitow
- }
- for(int i=0;i<h.Length;i++)// podzial pakietu na pole operacyjne, pole odpowiedzi i identyfikator
- {//dopelnienie jest nieistotne wiec jest ignorowane
- if (i <= 5)
- a[0] =a[0]+ h[i];
- if (i > 5 && i <= 9)
- a[1] = a[1] + h[i];
- if (i > 9 && i <= 17)
- a[2] = a[2] + h[i];
- }
- return a;
- }
- public static string RandomString(int length)// funckja losujaca id sesji
- {
- string liczba;
- if(connected_hosts==1)
- {
- int h = random.Next(0, 122);
- liczba = ToBin(h,8);
- }
- else
- {
- int h = random.Next(122, 254);
- liczba = ToBin(h, 8);
- }
- return liczba;
- }
- static byte [] TellAction(byte[] c,ref string h)//ustalanie akcji na podstawie pola operacji
- {
- byte[] bytes = new byte[3];
- string[] packet = new string[3];
- packet = DecodePacket(c);
- switch (packet[0])
- {
- case "000000":
- {
- h = RandomString(8);
- bytes = ProtocolBuilder("100000", "0000", h);
- break;
- }
- case "010000":
- {
- string l = ToBin(sekretna, 4);
- if (l == packet[1])
- {
- bytes = ProtocolBuilder("110000", "0000", h);
- game_state = 1;
- }
- else
- bytes = ProtocolBuilder("001000", "0000", h);
- break;
- }
- case "110100":
- {
- //connected_hosts--;
- //game_state = 1;
- break;
- }
- }
- return bytes;
- }
- public static void SecondChannel(int port, string h)//kanal w ktorym do serwer inicjuje komunikacje
- {
- IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port+10);
- UdpClient newsock = new UdpClient(ipep);
- IPEndPoint sender = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0);
- ReceivePacket(ref newsock, ref sender, ref h);
- while (true)
- {
- if(game_state == 1)// wysylanie pakietu informujacego o koncu gry
- {
- byte[] newArray = new byte[3];
- if(time2==0)
- {
- newArray = ProtocolBuilder("111000", "0000", h);//timeout
- }
- else
- {
- newArray = ProtocolBuilder("111000", "1111", h);//liczba zostala zgadnieta
- }
- SendPacket(newsock, newArray, sender);
- }
- if(times_up==1 && game_state==0)
- {
- byte[] newArray = new byte[3];
- string czas = ToBin(time2,10);
- string part1 = "", part2 = "";
- for (int i = 0; i <= 3; i++)
- part1 = part1+czas[i];
- for (int i = 4; i <10; i++)
- part2 = part2 + czas[i];
- newArray = ProtocolBuilder("101000", part1, h, part2);
- SendPacket(newsock, newArray, sender);
- Console.WriteLine("Wysylam pakiet czasu");
- times_up = 0;
- }
- }
- }
- public static void CallToChildThread(int port,ref string h)
- {
- int g=0;
- byte[] data = new byte[3];
- string c = h;
- Thread thread3 = new Thread(() => SecondChannel(port, c));
- IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
- UdpClient newsock = new UdpClient(ipep);
- IPEndPoint sender = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0);
- byte[] bytes = new byte[3];
- data = ReceivePacket(ref newsock, ref sender, ref h);
- bytes=TellAction(data, ref h);
- SendPacket(newsock, bytes, sender);
- connected_hosts++;
- thread3.Start();
- while (true)
- {
- if(g==0 && connected_hosts==2)//czeka na polaczenie obu hostow po czym wysyla informacje o rozpoczeciu rozgrywki
- {
- g = 1;
- byte[] newArray = new byte[3];
- newArray = ProtocolBuilder("100100", "0000", h);
- SendPacket(newsock, newArray, sender);
- }
- if (g == 1 && connected_hosts == 2)//pobiera liczbe wyslana przez klienta i odsyla prawda/falsz
- {
- data = ReceivePacket(ref newsock, ref sender, ref h);
- bytes = TellAction(data, ref h);
- SendPacket(newsock, bytes, sender);
- }
- }
- }
- static void SendPacket(UdpClient klient,byte [] bytes,IPEndPoint sender)//wysyla dane po czym czeka na potwierdzenie
- {
- klient.Send(bytes, bytes.Length, sender);
- klient.Receive(ref sender);
- }
- static byte[] ReceivePacket(ref UdpClient klient,ref IPEndPoint sender,ref string h )//zapisuje wyslane dane i potwierdza ich odebranie
- {
- byte[] ACK = new byte[3];
- byte[] data = new byte[3];
- data = klient.Receive(ref sender);
- ACK= ProtocolBuilder("111111", "0000", h);
- klient.Send(ACK, ACK.Length, sender);
- return data;
- }
- public static void Main()
- {
- byte[] data = new byte[3];
- string h1 = "00000000";
- string h2 = "00000000";
- Console.Write("Losowa liczba to: ");
- Console.Write(sekretna);
- Thread thread2 = new Thread(() => CallToChildThread(9050,ref h1));//po jednym watku dla kazdego klienta
- Thread thread3 = new Thread(() => CallToChildThread(9051,ref h2));
- thread2.Start();
- thread3.Start();
- while(true)//zatrzymuje watek do momentu polaczenia dwoch klientow, niesamowicie oszczedne rozwiazanie
- {
- if (connected_hosts == 2)
- break;
- }
- Thread timer = new Thread(() => Timer( h1, h2));
- timer.Start();
- int a = Console.Read();
- }
- }