00001
00002
00003
00004
00005
00006 namespace NewGamePhysics.Networking
00007 {
00008 using System;
00009 using System.Collections.Generic;
00010 using System.Net;
00011 using System.Net.Sockets;
00012 using System.Text;
00013 using System.Threading;
00014
00018 public class InfoLinkTransmitter : InfoLinkNetBase
00019 {
00023 private const int PollingInterval = 1000;
00024
00028 private const int TransmissionInterval = 100;
00029
00033 private object syncRoot = new object();
00034
00038 private List<InfoLink> transmitQueue = new List<InfoLink>();
00039
00043 private volatile bool running = false;
00044
00048 private Thread transmitterThread;
00049
00053 private long transmitted;
00054
00058 private long errors;
00059
00064 public InfoLinkTransmitter()
00065 {
00066 this.port = InfoLinkNetDefaultPort;
00067 }
00068
00074 public InfoLinkTransmitter(int port)
00075 {
00076 this.port = port;
00077 }
00078
00082 public bool Running
00083 {
00084 get { return this.running; }
00085 set { this.running = value; }
00086 }
00087
00091 public long Errors
00092 {
00093 get {
00094 return Interlocked.Read(ref this.errors);
00095 }
00096 }
00097
00101 public long Transmitted
00102 {
00103 get
00104 {
00105 return Interlocked.Read(ref this.transmitted);
00106 }
00107 }
00108
00112 ~InfoLinkTransmitter()
00113 {
00114 if (this.Connected)
00115 {
00116 this.Close();
00117 }
00118 }
00119
00123 public void StartTransmitter()
00124 {
00125 if (this.Connected)
00126 {
00127 this.Close();
00128 }
00129
00130 this.Open();
00131 this.transmitterThread = new Thread(new ThreadStart(RunTransmitterThread));
00132 this.transmitterThread.Name = "InfoLink Transmitter";
00133 this.transmitterThread.IsBackground = true;
00134 this.transmitterThread.Start();
00135 }
00136
00140 public void StopTransmitter()
00141 {
00142 if (this.Connected)
00143 {
00144 this.Close();
00145 }
00146 }
00147
00152 public void Transmit(InfoLink infoLink)
00153 {
00154
00155 lock (syncRoot)
00156 {
00157 transmitQueue.Add(infoLink);
00158 }
00159 }
00160
00165 public void Transmit(InfoLink[] infoLinks)
00166 {
00167
00168 lock (syncRoot)
00169 {
00170 transmitQueue.AddRange(infoLinks);
00171 }
00172 }
00173
00177 private void RunTransmitterThread()
00178 {
00179 this.running = this.Connected;
00180
00181 while (this.running)
00182 {
00183
00184 InfoLink infoLink = null;
00185 lock (syncRoot)
00186 {
00187 if (transmitQueue.Count > 0)
00188 {
00189
00190 infoLink = transmitQueue[0];
00191 transmitQueue.RemoveAt(0);
00192 }
00193 }
00194
00195
00196 if (infoLink != null)
00197 {
00198 string message = InfoLinkSerializer.Serialize(infoLink);
00199 byte[] sendbuf = Encoding.UTF8.GetBytes(message);
00200
00201 try
00202 {
00203 int bytesSent;
00204
00205 bytesSent = this.udpClient.Send(sendbuf, sendbuf.Length);
00206 if (bytesSent == sendbuf.Length)
00207 {
00208 Interlocked.Increment(ref this.transmitted);
00209 }
00210 else
00211 {
00212 Interlocked.Increment(ref this.errors);
00213 }
00214 }
00215 catch
00216 {
00217 Interlocked.Increment(ref this.errors);
00218 }
00219
00220
00221 Thread.Sleep(TransmissionInterval);
00222 }
00223 else
00224 {
00225
00226 Thread.Sleep(PollingInterval);
00227 }
00228 }
00229 }
00230
00234 private void Open()
00235 {
00236 this.udpClient = new UdpClient();
00237 this.endPoint = new IPEndPoint(IPAddress.Broadcast, this.port);
00238 this.udpClient.EnableBroadcast = true;
00239 this.udpClient.Connect(this.endPoint);
00240 this.Connected = true;
00241 this.errors = 0;
00242 }
00243
00247 private void Close()
00248 {
00249 try
00250 {
00251 this.running = false;
00252 this.udpClient.Close();
00253 this.transmitterThread = null;
00254 }
00255 finally
00256 {
00257 this.Connected = false;
00258 }
00259 }
00260 }
00261 }