├── AsycServer
├── obj
│ └── Debug
│ │ ├── TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
│ │ ├── TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
│ │ ├── TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
│ │ ├── AsycServer.exe
│ │ ├── AsycServer.pdb
│ │ ├── AsycServer.csprojResolveAssemblyReference.cache
│ │ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ │ └── AsycServer.csproj.FileListAbsolute.txt
├── bin
│ └── Debug
│ │ ├── AsycServer.exe
│ │ ├── AsycServer.pdb
│ │ ├── AsycServer.vshost.exe
│ │ ├── AsycServer.exe.config
│ │ ├── AsycServer.vshost.exe.config
│ │ └── AsycServer.vshost.exe.manifest
├── App.config
├── cProto.cs
├── CharData.cs
├── Properties
│ └── AssemblyInfo.cs
├── Client.cs
├── AsycServer.csproj
├── MessageBuffer.cs
├── Program.cs
└── AsyUdpServer.cs
├── AsycServer.v12.suo
├── README.md
├── .gitattributes
├── .gitignore
└── AsycServer.sln
/AsycServer/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/AsycServer.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer.v12.suo
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AsycServer
2 | 项目说明见博客http://blog.csdn.net/l_jinxiong/article/details/48917715
3 |
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/bin/Debug/AsycServer.exe
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/bin/Debug/AsycServer.pdb
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/AsycServer.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/obj/Debug/AsycServer.exe
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/AsycServer.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/obj/Debug/AsycServer.pdb
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.vshost.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/bin/Debug/AsycServer.vshost.exe
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/AsycServer.csprojResolveAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/obj/Debug/AsycServer.csprojResolveAssemblyReference.cache
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caolaoyao/AsycServer/HEAD/AsycServer/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/AsycServer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.vshost.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/AsycServer/cProto.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace AsycServer
8 | {
9 | public class cProto
10 | {
11 | public const int CONNECT = 100;
12 | public const int READY = 101;
13 | public const int SYNC_POS = 102;
14 | public const int SYNC_KEY = 103;
15 | public const int START = 104;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AsycServer/obj/Debug/AsycServer.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | D:\visual studio 2013\AsycServer\AsycServer\bin\Debug\AsycServer.exe.config
2 | D:\visual studio 2013\AsycServer\AsycServer\bin\Debug\AsycServer.exe
3 | D:\visual studio 2013\AsycServer\AsycServer\bin\Debug\AsycServer.pdb
4 | D:\visual studio 2013\AsycServer\AsycServer\obj\Debug\AsycServer.csprojResolveAssemblyReference.cache
5 | D:\visual studio 2013\AsycServer\AsycServer\obj\Debug\AsycServer.exe
6 | D:\visual studio 2013\AsycServer\AsycServer\obj\Debug\AsycServer.pdb
7 |
--------------------------------------------------------------------------------
/AsycServer/bin/Debug/AsycServer.vshost.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear on external disk
35 | .Spotlight-V100
36 | .Trashes
37 |
38 | # Directories potentially created on remote AFP share
39 | .AppleDB
40 | .AppleDesktop
41 | Network Trash Folder
42 | Temporary Items
43 | .apdisk
44 |
--------------------------------------------------------------------------------
/AsycServer/CharData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace AsycServer
8 | {
9 | public class CharData
10 | {
11 | public int roleId;
12 | public string name;
13 |
14 | public CharData(string str)
15 | {
16 | string[] playStr = str.Split('#');
17 | roleId = int.Parse(playStr[0]);
18 | name = playStr[1];
19 | }
20 |
21 | public CharData(int roleId, string name)
22 | {
23 | this.roleId = roleId;
24 | this.name = name;
25 | }
26 |
27 | public override string ToString()
28 | {
29 | string str = roleId + "#" + name;
30 | return str;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/AsycServer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.40629.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AsycServer", "AsycServer\AsycServer.csproj", "{56DDFAA5-EDAF-4882-997E-06783D471BC6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {56DDFAA5-EDAF-4882-997E-06783D471BC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {56DDFAA5-EDAF-4882-997E-06783D471BC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {56DDFAA5-EDAF-4882-997E-06783D471BC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {56DDFAA5-EDAF-4882-997E-06783D471BC6}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/AsycServer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过以下
6 | // 特性集控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("AsycServer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AsycServer")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("352f990c-d3e6-42dd-9abb-2d0c1c71f526")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/AsycServer/Client.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 |
11 | namespace AsycServer
12 | {
13 | public class Client
14 | {
15 | public int ID;
16 | public IPEndPoint tcpAdress, udpAdress;
17 | AsyUdpServer server;
18 | Socket socket;
19 | Stopwatch pingWatch;
20 |
21 | public bool Pinging
22 | {
23 | get
24 | {
25 | return pingWatch != null;
26 | }
27 | }
28 |
29 | public Client(int id, Socket sock, AsyUdpServer serv)
30 | {
31 | ID = id;
32 | server = serv;
33 | socket = sock;
34 |
35 | tcpAdress = (IPEndPoint)sock.RemoteEndPoint;
36 | Thread t = new Thread(AliveThread);
37 | t.Start();
38 | }
39 |
40 | public void SendAcceptPoll()
41 | {
42 | socket.Send(BitConverter.GetBytes(ID));
43 | }
44 |
45 | void AliveThread()
46 | {
47 | while (IsConnected() && server.Active)
48 | {
49 | Thread.Sleep(1000);
50 | }
51 |
52 | Disconnect();
53 | }
54 |
55 | bool IsConnected()
56 | {
57 | try
58 | {
59 | if (udpAdress != null) socket.Send(new byte[] { 0 });
60 | return true;
61 | }
62 | catch (SocketException e)
63 | {
64 | return false;
65 | }
66 | catch (Exception e)
67 | {
68 | server.CatchException(e);
69 | return false;
70 | }
71 | }
72 |
73 | public void Send(MessageBuffer msg)
74 | {
75 | server.Send(msg, this);
76 | }
77 |
78 | public void Disconnect()
79 | {
80 | if (socket == null) return;
81 |
82 | socket.Close();
83 | socket = null;
84 | server.ClientDisconnected(this);
85 | }
86 |
87 | public void Ping()
88 | {
89 | if (Pinging)
90 | {
91 | server.PingResult(this, pingWatch.Elapsed.Milliseconds);
92 | pingWatch = null;
93 | }
94 | else
95 | {
96 | pingWatch = Stopwatch.StartNew();
97 | server.Send(new MessageBuffer(new byte[] { AsyUdpServer.pingByte }), this);
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/AsycServer/AsycServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {56DDFAA5-EDAF-4882-997E-06783D471BC6}
8 | Exe
9 | Properties
10 | AsycServer
11 | AsycServer
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/AsycServer/MessageBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace AsycServer
8 | {
9 | public class MessageBuffer
10 | {
11 | List byteList = new List();
12 | int cursor = 0;
13 |
14 | public byte[] Array
15 | {
16 | get
17 | {
18 | return byteList.ToArray();
19 | }
20 | }
21 |
22 | public int Size
23 | {
24 | get
25 | {
26 | return byteList.Count;
27 | }
28 | }
29 |
30 | public MessageBuffer()
31 | {
32 | }
33 |
34 | public MessageBuffer(byte[] data)
35 | {
36 | byteList.AddRange(data);
37 | }
38 |
39 | public void MoveCursor(int n)
40 | {
41 | cursor += n;
42 | }
43 | public void Reset()
44 | {
45 | cursor = 0;
46 | }
47 |
48 | public byte ReadByte()
49 | {
50 | byte ret = byteList[cursor];
51 | MoveCursor(1);
52 |
53 | return ret;
54 | }
55 |
56 | public short ReadShort()
57 | {
58 | short ret = BitConverter.ToInt16(byteList.ToArray(), cursor);
59 | MoveCursor(2);
60 |
61 | return ret;
62 | }
63 |
64 | public int ReadInt()
65 | {
66 | int ret = BitConverter.ToInt32(byteList.ToArray(), cursor);
67 | MoveCursor(4);
68 |
69 | return ret;
70 | }
71 |
72 | public float ReadFloat()
73 | {
74 | float ret = BitConverter.ToSingle(byteList.ToArray(), cursor);
75 | MoveCursor(4);
76 |
77 | return ret;
78 | }
79 |
80 | public double ReadDouble()
81 | {
82 | double ret = BitConverter.ToDouble(byteList.ToArray(), cursor);
83 | MoveCursor(8);
84 |
85 | return ret;
86 | }
87 |
88 | public string ReadString()
89 | {
90 | int len = ReadInt();
91 |
92 | string s = "";
93 | for (int i = 0; i < len; i++)
94 | s += (char)ReadByte();
95 |
96 | return s;
97 | }
98 |
99 | public void WriteByte(short b) { WriteByte((byte)b); }
100 | public void WriteByte(int b) { WriteByte((byte)b); }
101 | public void WriteByte(byte b)
102 | {
103 | byteList.Add(b);
104 | }
105 |
106 | public void WriteShort(int s) { WriteShort((short)s); }
107 | public void WriteShort(short s)
108 | {
109 | byteList.AddRange(BitConverter.GetBytes(s));
110 | }
111 |
112 | public void WriteInt(int i)
113 | {
114 | byteList.AddRange(BitConverter.GetBytes(i));
115 | }
116 |
117 | public void WriteFloat(float f)
118 | {
119 | byteList.AddRange(BitConverter.GetBytes(f));
120 | }
121 |
122 | public void WriteDouble(double d)
123 | {
124 | byteList.AddRange(BitConverter.GetBytes(d));
125 | }
126 |
127 | public void WriteString(string s)
128 | {
129 | WriteInt(s.Length);
130 | for (int i = 0; i < s.Length; i++)
131 | WriteByte((byte)s[i]);
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/AsycServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace AsycServer
9 | {
10 | class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | Program p = new Program();
15 | while (true)
16 | {
17 | p.Logic();
18 | Thread.Sleep(10);
19 | }
20 | }
21 |
22 | AsyUdpServer server;
23 | List clientList = new List();
24 | Dictionary userList = new Dictionary();
25 | Dictionary>> keyDic = new Dictionary>>();//关键帧
26 | private int roleId = 100000; //客户端的人物id
27 | private int frameCount = 1; //当前帧数
28 |
29 | public Program()
30 | {
31 | server = new AsyUdpServer(1255, 1337);
32 |
33 | AsyUdpServer.DebugInfo.upData = true;
34 |
35 | server.OnStart += OnStart;
36 | server.OnConnect += OnConnect;
37 | server.OnMessage += OnMessage;
38 | server.OnDisconnect += OnDisconnect;
39 | server.OnDebug += OnDebug;
40 |
41 | Thread t = new Thread(InputThread);
42 | t.Start();
43 | }
44 |
45 | public void Logic()
46 | {
47 | server.Update();
48 | }
49 |
50 | public void OnStart()
51 | {
52 | Console.WriteLine("Server started!");
53 | }
54 |
55 | public void OnConnect(Client c)
56 | {
57 | Console.WriteLine("{0}[{1}, {2}] connected!", c.ID, c.tcpAdress, c.udpAdress);
58 | clientList.Add(c);
59 |
60 | MessageBuffer msg = new MessageBuffer();
61 | msg.WriteInt(cProto.CONNECT);
62 | msg.WriteInt(roleId);
63 | c.Send(msg);
64 | roleId++;
65 | }
66 |
67 | public void OnMessage(Client c, MessageBuffer msg)
68 | {
69 | int cproto = msg.ReadInt();
70 | switch(cproto)
71 | {
72 | case cProto.CONNECT:
73 | break;
74 | case cProto.READY:
75 | if (!userList.ContainsKey(c))
76 | {
77 | int id = msg.ReadInt();
78 | userList.Add(c, id);
79 | }
80 | //所有的玩家都准备好了,可以开始同步
81 | if(userList.Count >= clientList.Count)
82 | {
83 | frameCount = 1;
84 | keyDic = new Dictionary>>();
85 | string playStr = "";
86 | List playList = new List();
87 | foreach(var play in userList)
88 | {
89 | CharData charData = new CharData(play.Value, play.Value+ "_" + play.Value);
90 | playList.Add(charData.ToString());
91 | }
92 | playStr = string.Join(";", playList.ToArray());
93 | MessageBuffer buff = new MessageBuffer();
94 | buff.WriteInt(cProto.START);
95 | buff.WriteString(playStr);
96 |
97 | for (int i = 0; i < clientList.Count; ++i)
98 | {
99 | clientList[i].Send(buff);
100 | }
101 | }
102 | break;
103 | case cProto.SYNC_POS:
104 | for (int i = 0; i < clientList.Count; ++i)
105 | {
106 | if(c == clientList[i])
107 | {
108 | continue;
109 | }
110 | clientList[i].Send(msg);
111 | }
112 | break;
113 | case cProto.SYNC_KEY:
114 | int clientCurFrameCount = msg.ReadInt();
115 | string keyStr = msg.ReadString();
116 | if(keyDic.ContainsKey(clientCurFrameCount))
117 | {
118 | if(keyDic[clientCurFrameCount].ContainsKey(userList[c]))
119 | {
120 | keyDic[clientCurFrameCount][userList[c]].Add(keyStr);
121 | }
122 | else
123 | {
124 | keyDic[clientCurFrameCount][userList[c]] = new List();
125 | keyDic[clientCurFrameCount][userList[c]].Add(keyStr);
126 | }
127 | }
128 | else
129 | {
130 | keyDic[clientCurFrameCount] = new Dictionary>();
131 | keyDic[clientCurFrameCount][userList[c]] = new List();
132 | keyDic[clientCurFrameCount][userList[c]].Add(keyStr);
133 | }
134 | if(clientCurFrameCount == frameCount)
135 | {
136 | if(keyDic[clientCurFrameCount].Count == clientList.Count)
137 | {
138 | List keyDataList = new List();
139 | foreach(var dataList in keyDic[clientCurFrameCount].Values)
140 | {
141 | keyDataList.AddRange(dataList);
142 | }
143 |
144 | string keyData = string.Join(";", keyDataList.ToArray());
145 | MessageBuffer buff = new MessageBuffer();
146 | buff.WriteInt(cProto.SYNC_KEY);
147 | buff.WriteInt(frameCount);
148 | buff.WriteString(keyData);
149 | for (int i = 0; i < clientList.Count; ++i)
150 | {
151 | clientList[i].Send(buff);
152 | }
153 | frameCount += 1;
154 | }
155 | }
156 | break;
157 | case cProto.START:
158 | break;
159 | }
160 | }
161 |
162 | public void OnDisconnect(Client c)
163 | {
164 | Console.WriteLine("{0}[{1}, {2}] disconnected!", c.ID, c.tcpAdress, c.udpAdress);
165 | clientList.Remove(c);
166 | if(userList.ContainsKey(c))
167 | {
168 | userList.Remove(c);
169 | }
170 | }
171 |
172 | public void OnDebug(string s)
173 | {
174 | Console.ForegroundColor = ConsoleColor.Green;
175 | Console.WriteLine(s);
176 | Console.ForegroundColor = ConsoleColor.Gray;
177 | }
178 |
179 | public void InputThread()
180 | {
181 | while (true)
182 | {
183 | string input = Console.ReadLine();
184 |
185 | if (server.Active)
186 | {
187 | string[] inputArgs = input.Split(' ');
188 | if (inputArgs[0] == "quit") server.Close();
189 | if (inputArgs[0] == "kick") server.GetClient(int.Parse(inputArgs[1])).Disconnect();
190 | }
191 | else
192 | {
193 | if (input == "start") server.StartUp("127.0.0.1");
194 | }
195 | }
196 | }
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/AsycServer/AsyUdpServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Net.Sockets;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace AsycServer
11 | {
12 | public class AsyUdpServer
13 | {
14 | public static class DebugInfo
15 | {
16 | public static bool upData = false;
17 | public static bool downData = false;
18 | public static bool acceptData = false;
19 | }
20 |
21 | class MessageInfo
22 | {
23 | MessageBuffer message;
24 | IPEndPoint adress;
25 | AsyUdpServer server;
26 |
27 | public MessageBuffer Message
28 | {
29 | get
30 | {
31 | return message;
32 | }
33 | set
34 | {
35 | message = value;
36 | }
37 | }
38 | public IPEndPoint Adress
39 | {
40 | get
41 | {
42 | return adress;
43 | }
44 | set
45 | {
46 | adress = value;
47 | }
48 | }
49 |
50 | public MessageInfo(MessageBuffer message, IPEndPoint endPoint, AsyUdpServer s)
51 | {
52 | server = s;
53 | Message = message;
54 | Adress = endPoint;
55 | }
56 |
57 | public void Send()
58 | {
59 | server.udpSocket.Send(message.Array, message.Size, adress);
60 | }
61 | }
62 |
63 | public static byte pingByte = byte.MaxValue;
64 |
65 | static int upByteBuffer, downByteBuffer;
66 | static int upByteTotal, downByteTotal;
67 | public static int UpBytes
68 | {
69 | get
70 | {
71 | int n = upByteBuffer;
72 | upByteBuffer = 0;
73 |
74 | return n;
75 | }
76 | }
77 |
78 | public static int DownBytes
79 | {
80 | get
81 | {
82 | int n = downByteBuffer;
83 | downByteBuffer = 0;
84 |
85 | return n;
86 | }
87 | }
88 |
89 | public static int UpBytesTotal
90 | {
91 | get
92 | {
93 | return upByteTotal;
94 | }
95 | }
96 |
97 | public static int DownBytesTotal
98 | {
99 | get
100 | {
101 | return downByteTotal;
102 | }
103 | }
104 |
105 | public delegate void StartHandle();
106 | public delegate void ConnectHandle(Client c);
107 | public delegate void MessageHandle(Client c, MessageBuffer m);
108 | public delegate void MessageExtHandle(IPEndPoint ip, MessageBuffer m);
109 | public delegate void DisconnectHandle(Client c);
110 | public delegate void ExceptionHandle(Exception e);
111 | public delegate void PingHandle(Client c, int millis);
112 | public delegate void DebugHandle(string msg);
113 |
114 | int nmbrOfClients = 0;
115 |
116 | List disconnectedList = new List(), connectedList = new List();
117 | List clientList = new List();
118 | public Client GetClient(int id)
119 | {
120 | foreach (Client c in clientList)
121 | {
122 | if (c.ID == id)
123 | {
124 | return c;
125 | }
126 | }
127 | return null;
128 | }
129 |
130 | public Client GetClient(IPEndPoint ip)
131 | {
132 | foreach (Client c in clientList)
133 | {
134 | if (c.udpAdress != null && c.udpAdress.Equals(ip))
135 | {
136 | return c;
137 | }
138 | }
139 | return null;
140 | }
141 |
142 | public event StartHandle OnStart;
143 | public event ConnectHandle OnConnect;
144 | public event DisconnectHandle OnDisconnect;
145 | public event MessageHandle OnMessage;
146 | public event MessageExtHandle OnMessageExternal;
147 | public event ExceptionHandle OnException;
148 | public event PingHandle OnPing;
149 | public event DebugHandle OnDebug;
150 |
151 | List debugMessageList = new List();
152 | public void Debug(string s) { debugMessageList.Add(s); }
153 | List inMessages = new List(), outMessages = new List(),
154 | inMessagesExternal = new List();
155 |
156 | UdpClient udpSocket;
157 | TcpListener tcpSocket;
158 | int tcpPort, udpPort;
159 |
160 | Thread acceptThread, receiveThread, sendThread;
161 |
162 | public bool Active
163 | {
164 | get
165 | {
166 | return udpSocket != null && tcpSocket != null;
167 | }
168 | }
169 |
170 | public string LocalIP
171 | {
172 | get
173 | {
174 | IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
175 | string localIP = "";
176 |
177 | foreach (IPAddress ip in host.AddressList)
178 | {
179 | if (ip.AddressFamily == AddressFamily.InterNetwork)
180 | {
181 | localIP = ip.ToString();
182 | break;
183 | }
184 | }
185 |
186 | return localIP;
187 | }
188 | }
189 |
190 | public AsyUdpServer(int tcp, int udp)
191 | {
192 | tcpPort = tcp;
193 | udpPort = udp;
194 | }
195 |
196 | public void StartUp() { StartUp(LocalIP); }
197 | public void StartUp(string ip)
198 | {
199 | try
200 | {
201 | udpSocket = new UdpClient(udpPort);
202 | tcpSocket = new TcpListener(IPAddress.Any, tcpPort);
203 |
204 | acceptThread = new Thread(AcceptThread);
205 | receiveThread = new Thread(ReceiveThread);
206 | sendThread = new Thread(SendThread);
207 |
208 | acceptThread.Start();
209 | receiveThread.Start();
210 | sendThread.Start();
211 |
212 | OnStart();
213 | }
214 | catch (Exception e)
215 | {
216 | CatchException(e);
217 | }
218 | }
219 |
220 |
221 | public void Update()
222 | {
223 | while (inMessages.Count > 0)
224 | {
225 | OnMessage(GetClient(inMessages[0].Adress), inMessages[0].Message);
226 | inMessages.RemoveAt(0);
227 | }
228 |
229 | while (inMessagesExternal.Count > 0)
230 | {
231 | OnMessageExternal(inMessagesExternal[0].Adress, inMessagesExternal[0].Message);
232 | inMessagesExternal.RemoveAt(0);
233 | }
234 |
235 | while (connectedList.Count > 0)
236 | {
237 | OnConnect(connectedList[0]);
238 | connectedList.RemoveAt(0);
239 | }
240 |
241 | while (disconnectedList.Count > 0)
242 | {
243 | OnDisconnect(disconnectedList[0]);
244 | disconnectedList.RemoveAt(0);
245 | }
246 |
247 | while (debugMessageList.Count > 0)
248 | {
249 | OnDebug(debugMessageList[0]);
250 | debugMessageList.RemoveAt(0);
251 | }
252 | }
253 |
254 | void AcceptThread()
255 | {
256 | tcpSocket.Start();
257 |
258 | while (Active)
259 | {
260 | try
261 | {
262 | Socket s = tcpSocket.AcceptSocket();
263 | ClientConnected(s);
264 | }
265 | catch (Exception e)
266 | {
267 | CatchException(e);
268 | break;
269 | }
270 | }
271 | }
272 |
273 | void ReceiveThread()
274 | {
275 | while (Active)
276 | {
277 | try
278 | {
279 | IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
280 | byte[] data = udpSocket.Receive(ref ip);
281 |
282 | if (data.Length > 0)
283 | ReceiveData(data, ip);
284 | }
285 | catch (SocketException e)
286 | {
287 | //CatchException(e);
288 | continue;
289 | }
290 | catch (Exception e)
291 | {
292 | CatchException(e);
293 | continue;
294 | }
295 | }
296 | }
297 |
298 | void ReceiveData(byte[] data, IPEndPoint ip)
299 | {
300 | if (DebugInfo.downData && data.Length > 1)
301 | {
302 | string dataString = "";
303 | foreach (byte b in data) dataString += b + " ";
304 | Debug("Received " + data.Length + "[" + dataString + "]");
305 | }
306 |
307 | Client c = GetClient(ip);
308 |
309 | //Pinged
310 | if (data.Length == 1 && data[0] == pingByte)
311 | {
312 | if (c != null && c.Pinging)
313 | {
314 | c.Ping();
315 | }
316 | else
317 | {
318 | udpSocket.Send(data, 1, ip);
319 | }
320 |
321 | return;
322 | }
323 |
324 | else if (c != null)
325 | {
326 | inMessages.Add(new MessageInfo(new MessageBuffer(data), ip, this));
327 | }
328 | else if (data.Length == 4)
329 | {
330 | int id = BitConverter.ToInt32(data, 0);
331 | c = GetClient(id);
332 |
333 | if (c != null)
334 | {
335 | if (DebugInfo.acceptData) Debug("Received udp ip for ID " + id);
336 |
337 | c.udpAdress = ip;
338 | connectedList.Add(c);
339 | }
340 | }
341 | else
342 | {
343 | inMessagesExternal.Add(new MessageInfo(new MessageBuffer(data), ip, this));
344 | }
345 |
346 | downByteBuffer += data.Length;
347 | downByteTotal += data.Length;
348 | }
349 |
350 | void SendThread()
351 | {
352 | while (Active)
353 | {
354 | while (outMessages.Count > 0)
355 | {
356 | for (int i = 0; i < outMessages.Count; i++)
357 | {
358 | while (outMessages[i] == null) ;
359 |
360 | if (DebugInfo.downData && outMessages[0].Message.Size > 1)
361 | {
362 | string dataString = "";
363 | foreach (byte b in outMessages[0].Message.Array) dataString += b + " ";
364 | Debug("Sending " + outMessages[0].Message.Size + "[" + dataString + "]");
365 | }
366 |
367 | outMessages[i].Send();
368 | upByteBuffer += outMessages[i].Message.Size;
369 | upByteTotal += outMessages[i].Message.Size;
370 | }
371 |
372 | outMessages.Clear();
373 | }
374 |
375 | Thread.Sleep(5);
376 | }
377 | }
378 |
379 | void ClientConnected(Socket s)
380 | {
381 | Client c = new Client(nmbrOfClients, s, this);
382 | clientList.Add(c);
383 | c.SendAcceptPoll();
384 |
385 | nmbrOfClients++;
386 | }
387 |
388 | public void ClientDisconnected(Client c)
389 | {
390 | clientList.Remove(c);
391 | disconnectedList.Add(c);
392 | }
393 |
394 | public void Send(MessageBuffer msg, int id) { Send(msg, GetClient(id)); }
395 | public void Send(MessageBuffer msg, Client c)
396 | {
397 | if (c != null && c.udpAdress != null)
398 | outMessages.Add(new MessageInfo(msg, c.udpAdress, this));
399 | }
400 |
401 | public void SendExternal(MessageBuffer msg, IPEndPoint ip)
402 | {
403 | outMessages.Add(new MessageInfo(msg, ip, this));
404 | }
405 |
406 | public void Close()
407 | {
408 | if (tcpSocket == null || udpSocket == null) return;
409 |
410 | tcpSocket.Stop();
411 | udpSocket.Close();
412 |
413 | tcpSocket = null;
414 | udpSocket = null;
415 |
416 | acceptThread.Abort();
417 | sendThread.Abort();
418 | receiveThread.Abort();
419 |
420 | acceptThread = null;
421 | sendThread = null;
422 | receiveThread = null;
423 |
424 | List list = new List();
425 | list.AddRange(clientList);
426 |
427 | foreach (Client c in list) c.Disconnect();
428 | }
429 |
430 | public void CatchException(Exception e)
431 | {
432 | if (OnException != null) OnException(e);
433 | }
434 |
435 | public void PingResult(Client c, int millis)
436 | {
437 | if (OnPing != null) OnPing(c, millis);
438 | }
439 | }
440 | }
441 |
--------------------------------------------------------------------------------