I have a really weird problem. I tried everything to fix it and so far nothing works.
As you can see in the first image image, when I try to reference the static class "SharedConstants" from a namespace outside "UnnamedGameServer" the compiler returns the following error:
The type or namespace name 'ServerInfo' does not exist in the
namespace 'SharedConstants'
I found a turnaround to this problem referencing this class using UnnamedGameServer.SharedConstants instead of SharedConstants and using UnnamedGameServer; on the top of the .cs file. But I prefer avoiding referencing it on every line I use that class.
Here are some screenshots of my code:
First screenshot:
Second screenshot:
Edit: Screenshot of using statement:
Edit 2: Code without screenshots:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using ProtoBuf;
using UnnamedGameServer;
using System.Threading;
namespace Unnamed_game
{
class Connection
{
public struct UserInformation
{
public string Username;
public int UserID;
}
static private Connection instance;
private Connection()
{
client = new TcpClient();
header = new PacketHeader();
_isLoggedCharacter = false;
_isLoggedUser = false;
magicByte = UnnamedGameServer.SharedConstants.ServerInfo.MagicByte;
}
// properties
TcpClient client;
PacketHeader header;
Thread serverCommThread;
byte[] magicByte;
bool _isLoggedCharacter;
CharacterInformation chInformation
{
get
{
return Player.Instance().Information;
}
}
bool _isLoggedUser;
public UserInformation Information;
// methods
static public Connection Instance()
{
if(instance == null)
{
instance = new Connection();
return instance;
}
else
{
return instance;
}
}
/// <summary>
/// Should never be used. Use the parameterless one to get the server address and information. It doesn't use try-catch, the exception handling should be done on Game1.Initialize()
/// </summary>
public void ConnectServer(IPEndPoint endPoint)
{
if (client.Connected)
{
return;
}
else
{
client.Connect(endPoint);
serverCommThread = new Thread(HandleServerCommunication);
serverCommThread.Start();
}
}
public void ConnectServer()
{
this.ConnectServer(new IPEndPoint(UnnamedGameServer.SharedConstants.ServerInfo.ServerAddress, UnnamedGameServer.SharedConstants.ServerInfo.Port));
}
private void HandleServerCommunication()
{
if (client == null)
{
throw new Exception("The TcpClient is null");
}
else
{
// this doesn't work
byte[] magicByte = SharedConstants.ServerInfo.MagicByte;
// this works
magicByte = UnnamedGameServer.SharedConstants.ServerInfo.MagicByte;
}
}
private void SendPacket(ActionType actionType, object packetStruct)
{
try
{
header.ActionTypeNumber = (short)actionType;
using (NetworkStream stream = client.GetStream())
{
stream.Write(magicByte, 0, magicByte.Length);
Serializer.SerializeWithLengthPrefix<PacketHeader>(stream, header, PrefixStyle.Base128);
switch (actionType)
{
case ActionType.Connect:
Serializer.SerializeWithLengthPrefix<PacketConnect>(stream, (PacketConnect)packetStruct, PrefixStyle.Base128);
break;
}
stream.Write(magicByte, 0, magicByte.Length);
}
}
catch (Exception)
{
// error
return;
}
}
public void CreateNewCharacter(string characterName, CharacterClass chClass, CharacterRace chRace)
{
var info = new NewCharacterInfo();
info.Name = characterName;
info.OwnerUsername = Information.Username;
info.Class = chClass;
info.Race = chRace;
CreateNewCharacter(info);
}
public void CreateNewCharacter(NewCharacterInfo info)
{
var packet = new PacketCreateNewCharacter();
packet.chInfo = info;
SendPacket(ActionType.CreateNewCharacter, packet);
}
public void ConnectUser(string username, string unhashedPassword)
{
var packet = new PacketConnect();
packet.Username = username;
packet.UnhashedPassword = unhashedPassword;
ConnectUser(packet);
}
public void ConnectUser(PacketConnect packet)
{
if (_isLoggedCharacter || _isLoggedUser)
{
return;
}
else
{
SendPacket(ActionType.Connect, packet);
}
}
public void ConnectCharacter(string characterName, short serverID)
{
var packet = new PacketLoginCharacter();
packet.CharacterName = characterName;
packet.ServerID = serverID;
ConnectCharacter(packet);
}
public void ConnectCharacter(PacketLoginCharacter packet)
{
if (_isLoggedCharacter || !_isLoggedUser)
{
return;
}
else
{
SendPacket(ActionType.LoginCharacter, packet);
}
}
public void Disconnect(PacketDisconnect packet)
{
if (!_isLoggedUser)
{
return;
}
else
{
SendPacket(ActionType.Disconnect, packet);
}
}
}
}
edit 3:: Code where SharedConstants is stored.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace UnnamedGameServer
{
/// <summary>
/// ALL CONSTANTS THAT ARE SHARED BY THE CLIENT AND THE SERVER ARE STORED HERE. DONT ADD MORE CLASSES THAT STORE CONSTANTS. Use GameConstants for game-only constants.
/// </summary>
public static class SharedConstants
{
/// <summary>
/// Server information with port, IP and MagicByte
/// </summary>
public static class ServerInfo
{
public const short Port = 6483;
public static readonly IPAddress ServerAddress = IPAddress.Loopback;
public static byte[] MagicByte
{
get
{
return new byte[4] { 0xF1, 0x64, 0x83, 0xC4 };
}
}
}
/// <summary>
/// Character constants shared by client/server
/// </summary>
public static class CharacterConstants
{
public static class Movement
{
/// <summary>
/// Coordinates per update
/// </summary>
public const float DefaultCoordinatePerUpdate = 8;
public const float ModifierNormal = 1f;
public const float ModifierFrozen = 0.8f;
public const float ModifierSpeedBuff = 1.2f;
public const float ModifierStop = 0f;
}
}
/// <summary>
/// Networking constants
/// </summary>
public static class Networking
{
public const int MilisecondsPerMovementUpdate = 100;
public const ushort ActionTypeNonMetaActionStart = 0x0FFF + 1;
/// <summary>
/// What is the number of actions a non-logged user can perform
/// </summary>
public const ushort ActionTypeNonLoggedUser = 0x000F;
}
}
enum CharacterDirection
{
NoMovement = 0x00,
Top = 0x01,
TopRight = 0x02,
TopLeft = 0x03,
Right = 0x04,
BottomRight = 0x05,
Bottom = 0x06,
BottomLeft = 0x07,
Left = 0x08
}
enum CharacterStatus
{
Alive = 0x01,
Dead = 0x02
}
enum CharacterClass
{
Mage = 0x01,
Knight = 0x02
}
enum CharacterRace
{
Human = 0x01
}
enum CharacterType
{
Player = 0x01,
GameMaster = 0x02
}
enum CharacterFaction
{
Newbie = 0x01,
Army = 0x02,
Chaos = 0x03
}
enum CharacterMovementStatus
{
Normal = 0x01,
Frozen = 0x02,
SpeedBuff = 0x03,
Stop = 0x04
}
struct CharacterExperience
{
public CharacterExperience(short level, int experience)
{
Level = level;
Experience = experience;
}
public short Level;
public int Experience;
}
}
Having a using statement should work. If there is any code before the using statements then this may cause a problem.
you could try putting the using statement after the namespace e.g:
namespace Unnamed_game
{
using UnamedGameServer;
class Connection
This should work:
using UnnamedGameServer;
class MyClass {
byte[] b = SharedConstants.ServerInfo.MagicByte;
}
If this doesn't solve your problem, please post the code (in text, not a screenshot) of a short but complete example showing the problem.
Related
I´m doing multiplayer and my Unity console writes this error "Cannot access a disposed object.
Object name: 'System.Net.Sockets.UdpClient'." when I close the server. I don't know what to do with it... Can anyone please advise me how to fix this?
This is my Server.cs file:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
public class Server
{
public static int MaxPlayers { get; private set; }
public static int Port { get; private set; }
public static Dictionary<int, Client> clients = new Dictionary<int, Client>();
public delegate void PacketHandler(int _fromClient, Packet _packet);
public static Dictionary<int, PacketHandler> packetHandlers;
private static TcpListener tcpListener;
private static UdpClient udpListener;
/// <summary>Starts the server.</summary>
/// <param name="_maxPlayers">The maximum players that can be connected simultaneously.</param>
/// <param name="_port">The port to start the server on.</param>
public static void Start(int _maxPlayers, int _port)
{
MaxPlayers = _maxPlayers;
Port = _port;
Debug.Log("Starting server...");
InitializeServerData();
tcpListener = new TcpListener(IPAddress.Any, Port);
tcpListener.Start();
tcpListener.BeginAcceptTcpClient(TCPConnectCallback, null);
udpListener = new UdpClient(Port);
udpListener.BeginReceive(UDPReceiveCallback, null);
Debug.Log($"Server started on port {Port}.");
}
/// <summary>Handles new TCP connections.</summary>
private static void TCPConnectCallback(IAsyncResult _result)
{
TcpClient _client = tcpListener.EndAcceptTcpClient(_result);
tcpListener.BeginAcceptTcpClient(TCPConnectCallback, null);
Debug.Log($"Incoming connection from {_client.Client.RemoteEndPoint}...");
for (int i = 1; i <= MaxPlayers; i++)
{
if (clients[i].tcp.socket == null)
{
clients[i].tcp.Connect(_client);
return;
}
}
Debug.Log($"{_client.Client.RemoteEndPoint} failed to connect: Server full!");
}
/// <summary>Receives incoming UDP data.</summary>
private static void UDPReceiveCallback(IAsyncResult _result)
{
try
{
IPEndPoint _clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] _data = udpListener.EndReceive(_result, ref _clientEndPoint);
udpListener.BeginReceive(UDPReceiveCallback, null);
if (_data.Length < 4)
{
return;
}
using (Packet _packet = new Packet(_data))
{
int _clientId = _packet.ReadInt();
if (_clientId == 0)
{
return;
}
if (clients[_clientId].udp.endPoint == null)
{
// If this is a new connection
clients[_clientId].udp.Connect(_clientEndPoint);
return;
}
if (clients[_clientId].udp.endPoint.ToString() == _clientEndPoint.ToString())
{
// Ensures that the client is not being impersonated by another by sending a false clientID
clients[_clientId].udp.HandleData(_packet);
}
}
}
catch (Exception _ex)
{
Debug.Log($"Error receiving UDP data: {_ex}");
}
}
/// <summary>Sends a packet to the specified endpoint via UDP.</summary>
/// <param name="_clientEndPoint">The endpoint to send the packet to.</param>
/// <param name="_packet">The packet to send.</param>
public static void SendUDPData(IPEndPoint _clientEndPoint, Packet _packet)
{
try
{
if (_clientEndPoint != null)
{
udpListener.BeginSend(_packet.ToArray(), _packet.Length(), _clientEndPoint, null, null);
}
}
catch (Exception _ex)
{
Debug.Log($"Error sending data to {_clientEndPoint} via UDP: {_ex}");
}
}
/// <summary>Initializes all necessary server data.</summary>
private static void InitializeServerData()
{
for (int i = 1; i <= MaxPlayers; i++)
{
clients.Add(i, new Client(i));
}
packetHandlers = new Dictionary<int, PacketHandler>()
{
{ (int)ClientPackets.welcomeReceived, ServerHandle.WelcomeReceived },
{ (int)ClientPackets.playerMovement, ServerHandle.PlayerMovement },
{ (int)ClientPackets.playerShoot, ServerHandle.PlayerShoot },
{ (int)ClientPackets.playerThrowItem, ServerHandle.PlayerThrowItem }
};
Debug.Log("Initialized packets.");
}
public static void Stop()
{
tcpListener.Stop();
udpListener.Close();
}
}
A tutorial according to which I make a multiplayer game:
https://www.youtube.com/playlist?list=PLXkn83W0QkfnqsK8I0RAz5AbUxfg3bOQ5
It's because the garbage collector has disposed the udpClient and you are trying to call the Stop() method in a disposed object.
So , try replacing this method instead of your Stop method
public static void Stop()
{
try
{
tcpListener.Stop();
udpListener.Close();
}
catch {}
}
I am trying to communicate with a PLC over modbus via RS232, but it simply keeps saying that my message from should contain at least 6 bytes of data.
First of all I am sorry for the outlining I always seem to struggle with the code input..., I used the same class for a TCP/IP modbus connection which seems to work quite good, now I am trying to do the same via RTU RS232
I added both of my classes in the edit, thanks in advance I hope someone can help me out.
namespace ConsoleApplication2
{
class Program
{
public static ModBusDriver modbusDriver;
static void Main(string[] args)
{
SerialPort port = new SerialPort("COM1");
port.BaudRate = 38400;
port.DataBits = 8;
port.ReadTimeout = 600;
port.WriteTimeout = 600;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
modbusDriver = new ModBusDriver(port);
modbusDriver.connect(1);
byte slaveAddress = 1;
modbusDriver.WriteMultipleCoils(slaveAddress, 8193, new bool[6] { false, false, false, false, false, false });
Console.WriteLine("done");
Console.Read();
}
Modbusdriver.cs
using Modbus.Device;
using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Threading;
namespace CoCoSModBusDriver
{
// based on nmodbus4:
// -https://github.com/NModbus4/NModbus4
class ModBusDriver
{
public int connected;
private bool gotClient = false;
public IModbusSerialMaster modbusConnector;
public SerialPort serialPort;
public ModBusDriver(SerialPort port)
{
serialPort = port;
modbusConnector = ModbusSerialMaster.CreateRtu(port);
}
public void connect(int retries)
{
int retryCounter = 0;
while (retryCounter < retries || retries == -1)
{
try
{
serialPort.Open();
}
catch (Exception ex)
{
retryCounter++;
Thread.Sleep(5000);
}
}
}
public void WriteMultipleCoils(byte slaveAdress, ushort startAdress, bool[] data)
{
try
{
modbusConnector.WriteMultipleCoils(slaveAdress, startAdress, data);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
You are missing the slave address in the request. From the IModbus master interface:
/// <summary>
/// Writes a sequence of coils.
/// </summary>
/// <param name="slaveAddress">Address of the device to write to.</param>
/// <param name="startAddress">Address to begin writing values.</param>
/// <param name="data">Values to write.</param>
void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] data);
You should use ModbusSerialMaster class. There is a good example at mesta automations homepage.
I am developing a virtual reality windows based game. I will be using an accelerometer sensor to get the hand movements of the player and use it in the game, where as the player will use it to fight an enemy in the game. I managed to get the accelerometer readings from the sensor.
I just need an idea on how I can now integrate it with my game in Unity. I used .Net to get the readings from the sensor. This is a TI simple link sensor tag (CC2650STK). This will connect via Bluetooth to my Windows phone.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;
using Buffer = Windows.Storage.Streams.Buffer;
namespace SensorTag
{
/// This class provides access to the SensorTag Accelerometer BLE data
public class BleAccelerometerService : BleGenericGattService
{
public BleAccelerometerService()
{
}
/// The version of the SensorTag device. 1=CC2541, 2=CC2650.
public int Version { get; set; }
static Guid AccelerometerServiceUuid = Guid.Parse("f000aa10-0451-4000-b000-000000000000");
static Guid AccelerometerCharacteristicUuid = Guid.Parse("f000aa11-0451-4000-b000-000000000000");
static Guid AccelerometerCharacteristicConfigUuid = Guid.Parse("f000aa12-0451-4000-b000-000000000000");
static Guid AccelerometerCharacteristicPeriodUuid = Guid.Parse("f000aa13-0451-4000-b000-000000000000");
Delegate _accelerometerValueChanged;
public event EventHandler<AccelerometerMeasurementEventArgs> AccelerometerMeasurementValueChanged
{
add
{
if (_accelerometerValueChanged != null)
{
_accelerometerValueChanged = Delegate.Combine(_accelerometerValueChanged, value);
}
else
{
_accelerometerValueChanged = value;
RegisterForValueChangeEvents(AccelerometerCharacteristicUuid);
}
}
remove
{
if (_accelerometerValueChanged != null)
{
_accelerometerValueChanged = Delegate.Remove(_accelerometerValueChanged, value);
if (_accelerometerValueChanged == null)
{
UnregisterForValueChangeEvents(AccelerometerCharacteristicUuid);
}
}
}
}
private async Task<int> GetConfig()
{
var ch = GetCharacteristic(AccelerometerCharacteristicConfigUuid);
if (ch != null)
{
var properties = ch.CharacteristicProperties;
if ((properties & GattCharacteristicProperties.Read) != 0)
{
var result = await ch.ReadValueAsync();
IBuffer buffer = result.Value;
DataReader reader = DataReader.FromBuffer(buffer);
var value = reader.ReadByte();
Debug.WriteLine("Acceleration config = " + value);
return (int)value;
}
}
return -1;
}
bool isReading;
public async Task StartReading()
{
if (!isReading)
{
await WriteCharacteristicByte(AccelerometerCharacteristicConfigUuid, 1);
isReading = true;
}
}
public async Task StopReading()
{
if (isReading)
{
isReading = false;
await WriteCharacteristicByte(AccelerometerCharacteristicConfigUuid, 0);
}
}
/// Get the rate at which accelerometer is being polled, in milliseconds.
/// </summary>
/// <returns>Returns the value read from the sensor or -1 if something goes wrong.</returns>
public async Task<int> GetPeriod()
{
byte v = await ReadCharacteristicByte(AccelerometerCharacteristicPeriodUuid, Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached);
return (int)(v * 10);
}
/// <summary>
/// Set the rate at which accelerometer is being polled, in milliseconds.
/// </summary>
/// <param name="milliseconds">The delay between updates, accurate only to 10ms intervals. Maximum value is 2550.</param>
public async Task SetPeriod(int milliseconds)
{
int delay = milliseconds / 10;
byte p = (byte)delay;
if (p < 1)
{
p = 1;
}
await WriteCharacteristicByte(AccelerometerCharacteristicPeriodUuid, p);
}
private void OnAccelerationMeasurementValueChanged(AccelerometerMeasurementEventArgs args)
{
if (_accelerometerValueChanged != null)
{
((EventHandler<AccelerometerMeasurementEventArgs>)_accelerometerValueChanged)(this, args);
}
}
public async Task<bool> ConnectAsync(string deviceContainerId)
{
return await this.ConnectAsync(AccelerometerServiceUuid, deviceContainerId);
}
protected override void OnCharacteristicValueChanged(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
if (sender.Uuid == AccelerometerCharacteristicUuid)
{
if (_accelerometerValueChanged != null)
{
uint dataLength = eventArgs.CharacteristicValue.Length;
using (DataReader reader = DataReader.FromBuffer(eventArgs.CharacteristicValue))
{
if (dataLength == 3)
{
var data = new byte[dataLength];
reader.ReadBytes(data);
AccelerometerMeasurement measurement = new AccelerometerMeasurement();
sbyte x = (sbyte)data[0];
sbyte y = (sbyte)data[1];
sbyte z = (sbyte)data[2];
measurement.X = (double)x / 64.0;
measurement.Y = (double)y / 64.0;
measurement.Z = (double)z / 64.0;
OnAccelerationMeasurementValueChanged(new AccelerometerMeasurementEventArgs(measurement, eventArgs.Timestamp));
}
}
}
}
}
}
public class AccelerometerMeasurement
{
/// <summary>
/// Get/Set X accelerometer in units of 1 g (9.81 m/s^2).
/// </summary>
public double X { get; set;}
/// <summary>
/// Get/Set Y accelerometer in units of 1 g (9.81 m/s^2).
/// </summary>
public double Y { get; set;}
/// <summary>
/// Get/Set Z accelerometer in units of 1 g (9.81 m/s^2).
/// </summary>
public double Z { get; set;}
public AccelerometerMeasurement()
{
}
}
public class AccelerometerMeasurementEventArgs : EventArgs
{
public AccelerometerMeasurementEventArgs(AccelerometerMeasurement measurement, DateTimeOffset timestamp)
{
Measurement = measurement;
Timestamp = timestamp;
}
public AccelerometerMeasurement Measurement
{
get;
private set;
}
public DateTimeOffset Timestamp
{
get;
private set;
}
}
}
One requirement would be to convert the acceleration values into quaternion:
private void ReadAcceleration(AccelerometerMeasurement measure){
Vector3 accel = new Vector3((float)measure.X,
(float)measure.Y, (float)measure.Z);
Quaternion rotation = Quaternion.LookRotation(accel,Vector3.forward);
}
The rotation quaternion can be used to set an object to the device rotation.
To keep the intro short, I will mention that I have been building an application that involves executing remote commands from a private website that I have built and having my personal home computer respond to those commands.
I discovered that live desktop-streaming would be a perfect feature, and I am planning to use an iframe to fit it into my site. However, I cannot seem to find a good C# library which will allow me to stream my desktop in realtime.
Other than this one: http://www.codeproject.com/Articles/371955/Motion-JPEG-Streaming-Server
The problem is, that only allows me to stream my desktop to localhost, 127.0.0.1, and the other local host links.
I need a way to modify it to be able to have it stream to a server of my choice, from which I can then access it. For example www.mystream.com/stream.php
It consists of two classes: ImageStreamingServer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.IO;
// -------------------------------------------------
// Developed By : Ragheed Al-Tayeb
// e-Mail : ragheedemail#gmail.com
// Date : April 2012
// -------------------------------------------------
namespace rtaNetworking.Streaming
{
/// <summary>
/// Provides a streaming server that can be used to stream any images source
/// to any client.
/// </summary>
public class ImageStreamingServer:IDisposable
{
private List<Socket> _Clients;
private Thread _Thread;
public ImageStreamingServer():this(Screen.Snapshots(600,450,true))
{
}
public ImageStreamingServer(IEnumerable<Image> imagesSource)
{
_Clients = new List<Socket>();
_Thread = null;
this.ImagesSource = imagesSource;
this.Interval = 50;
}
/// <summary>
/// Gets or sets the source of images that will be streamed to the
/// any connected client.
/// </summary>
public IEnumerable<Image> ImagesSource { get; set; }
/// <summary>
/// Gets or sets the interval in milliseconds (or the delay time) between
/// the each image and the other of the stream (the default is .
/// </summary>
public int Interval { get; set; }
/// <summary>
/// Gets a collection of client sockets.
/// </summary>
public IEnumerable<Socket> Clients { get { return _Clients; } }
/// <summary>
/// Returns the status of the server. True means the server is currently
/// running and ready to serve any client requests.
/// </summary>
public bool IsRunning { get { return (_Thread != null && _Thread.IsAlive); } }
/// <summary>
/// Starts the server to accepts any new connections on the specified port.
/// </summary>
/// <param name="port"></param>
public void Start(int port)
{
lock (this)
{
_Thread = new Thread(new ParameterizedThreadStart(ServerThread));
_Thread.IsBackground = true;
_Thread.Start(port);
}
}
/// <summary>
/// Starts the server to accepts any new connections on the default port (8080).
/// </summary>
public void Start()
{
this.Start(8080);
}
public void Stop()
{
if (this.IsRunning)
{
try
{
_Thread.Join();
_Thread.Abort();
}
finally
{
lock (_Clients)
{
foreach (var s in _Clients)
{
try
{
s.Close();
}
catch { }
}
_Clients.Clear();
}
_Thread = null;
}
}
}
/// <summary>
/// This the main thread of the server that serves all the new
/// connections from clients.
/// </summary>
/// <param name="state"></param>
private void ServerThread(object state)
{
try
{
Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Server.Bind(new IPEndPoint(IPAddress.Any,(int)state));
Server.Listen(10);
System.Diagnostics.Debug.WriteLine(string.Format("Server started on port {0}.", state));
foreach (Socket client in Server.IncommingConnectoins())
ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), client);
}
catch { }
this.Stop();
}
/// <summary>
/// Each client connection will be served by this thread.
/// </summary>
/// <param name="client"></param>
private void ClientThread(object client)
{
Socket socket = (Socket)client;
System.Diagnostics.Debug.WriteLine(string.Format("New client from {0}",socket.RemoteEndPoint.ToString()));
lock (_Clients)
_Clients.Add(socket);
try
{
using (MjpegWriter wr = new MjpegWriter(new NetworkStream(socket, true)))
{
// Writes the response header to the client.
wr.WriteHeader();
// Streams the images from the source to the client.
foreach (var imgStream in Screen.Streams(this.ImagesSource))
{
if (this.Interval > 0)
Thread.Sleep(this.Interval);
wr.Write(imgStream);
}
}
}
catch { }
finally
{
lock (_Clients)
_Clients.Remove(socket);
}
}
#region IDisposable Members
public void Dispose()
{
this.Stop();
}
#endregion
}
static class SocketExtensions
{
public static IEnumerable<Socket> IncommingConnectoins(this Socket server)
{
while(true)
yield return server.Accept();
}
}
static class Screen
{
public static IEnumerable<Image> Snapshots()
{
return Screen.Snapshots(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,true);
}
/// <summary>
/// Returns a
/// </summary>
/// <param name="delayTime"></param>
/// <returns></returns>
public static IEnumerable<Image> Snapshots(int width,int height,bool showCursor)
{
Size size = new Size(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
Bitmap srcImage = new Bitmap(size.Width, size.Height);
Graphics srcGraphics = Graphics.FromImage(srcImage);
bool scaled = (width != size.Width || height != size.Height);
Bitmap dstImage = srcImage;
Graphics dstGraphics = srcGraphics;
if(scaled)
{
dstImage = new Bitmap(width, height);
dstGraphics = Graphics.FromImage(dstImage);
}
Rectangle src = new Rectangle(0, 0, size.Width, size.Height);
Rectangle dst = new Rectangle(0, 0, width, height);
Size curSize = new Size(32, 32);
while (true)
{
srcGraphics.CopyFromScreen(0, 0, 0, 0, size);
if (showCursor)
Cursors.Default.Draw(srcGraphics,new Rectangle(Cursor.Position,curSize));
if (scaled)
dstGraphics.DrawImage(srcImage, dst, src, GraphicsUnit.Pixel);
yield return dstImage;
}
srcGraphics.Dispose();
dstGraphics.Dispose();
srcImage.Dispose();
dstImage.Dispose();
yield break;
}
internal static IEnumerable<MemoryStream> Streams(this IEnumerable<Image> source)
{
MemoryStream ms = new MemoryStream();
foreach (var img in source)
{
ms.SetLength(0);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
yield return ms;
}
ms.Close();
ms = null;
yield break;
}
}
}
MjpegWriter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
// -------------------------------------------------
// Developed By : Ragheed Al-Tayeb
// e-Mail : ragheedemail#gmail.com
// Date : April 2012
// -------------------------------------------------
namespace rtaNetworking.Streaming
{
/// <summary>
/// Provides a stream writer that can be used to write images as MJPEG
/// or (Motion JPEG) to any stream.
/// </summary>
public class MjpegWriter:IDisposable
{
private static byte[] CRLF = new byte[] { 13, 10 };
private static byte[] EmptyLine = new byte[] { 13, 10, 13, 10};
private string _Boundary;
public MjpegWriter(Stream stream)
: this(stream, "--boundary")
{
}
public MjpegWriter(Stream stream,string boundary)
{
this.Stream = stream;
this.Boundary = boundary;
}
public string Boundary { get; private set; }
public Stream Stream { get; private set; }
public void WriteHeader()
{
Write(
"HTTP/1.1 200 OK\r\n" +
"Content-Type: multipart/x-mixed-replace; boundary=" +
this.Boundary +
"\r\n"
);
this.Stream.Flush();
}
public void Write(Image image)
{
MemoryStream ms = BytesOf(image);
this.Write(ms);
}
public void Write(MemoryStream imageStream)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine(this.Boundary);
sb.AppendLine("Content-Type: image/jpeg");
sb.AppendLine("Content-Length: " + imageStream.Length.ToString());
sb.AppendLine();
Write(sb.ToString());
imageStream.WriteTo(this.Stream);
Write("\r\n");
this.Stream.Flush();
}
private void Write(byte[] data)
{
this.Stream.Write(data, 0, data.Length);
}
private void Write(string text)
{
byte[] data = BytesOf(text);
this.Stream.Write(data, 0, data.Length);
}
private static byte[] BytesOf(string text)
{
return Encoding.ASCII.GetBytes(text);
}
private static MemoryStream BytesOf(Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms;
}
public string ReadRequest(int length)
{
byte[] data = new byte[length];
int count = this.Stream.Read(data,0,data.Length);
if (count != 0)
return Encoding.ASCII.GetString(data, 0, count);
return null;
}
#region IDisposable Members
public void Dispose()
{
try
{
if (this.Stream != null)
this.Stream.Dispose();
}
finally
{
this.Stream = null;
}
}
#endregion
}
}
This application should work over internet as well. Make sure that the port you access through it remotely is open.
If you don't want to have to open a port for the app to work. then consider changing the source above to make a reverse connection instead , where your desktop computer acts as a client rather than a server.
Good luck
i had problem with application messaging, ...after some question and answer, i went to use Remoting namespace, under System.Runtime namespace...
it worked perfectly, but the matter is when application terminate with exception...
if server stop in not manner, the channel i register will stay registered, ...
i dont have much knowledge over remoting or other related matter...
but i checked some of things, and non didnt worked...
the article i went through done registering this way, and didnt unregister the application, and i use it in service, and seem service application host dont close just with service beign stopped...
here's my client class which is used in service applciation...
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace Remoting
{
public class Client
{
private RemotableObject remoteObject;
/// <summary>
/// Configure Client Class
/// </summary>
/// <param name="url">Something like: tcp://localhost:8080/HelloWorld</param>
public Client(string url)
{
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
remoteObject = (RemotableObject)Activator.GetObject(typeof(RemotableObject), url);
}
public void SetMessage(string message)
{
remoteObject.SetMessage(message);
}
}
}
as i noticed, the article give no information to the channel, so i'm wonder for unregistering it how should i find it.....
in the server APP, the article done givin host post at last
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace Remoting
{
public abstract class Server:IObserver
{
private RemotableObject remotableObject;
/// <summary>
/// Configure Server Class
/// </summary>
/// <param name="port">port number like: 8080</param>
/// <param name="url">Object url like: HelloWorld</param>
public Server(int port, string url)
{
remotableObject = new RemotableObject();
TcpChannel channel = new TcpChannel(port);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotableObject), url, WellKnownObjectMode.Singleton);
Cache.Attach(this);
}
public abstract void Notify(string message);
}
}
but, even know think i launch my application over a server that run an app with same port number, i do not want to un-register other application channels... what should i do?
BTW most issue is about the client that register a channel, with no information... how do i detect it? and unregister it, before service try to do that, and terminate with exception?
if it help, this is the error i already recieve:
Event Type: Error
Event Source: Event Reader Service
Event Category: None
Event ID: 0
Date: 8/20/2012
Time: 5:23:14 PM
User: N/A
Computer: HF-SERVER-PC
Description:
Service cannot be started.
System.Runtime.Remoting.RemotingException: The channel 'tcp' is
already registered. at
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannelInternal(IChannel
chnl, Boolean ensureSecurity) at
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel
chnl) at Remoting.Client..ctor(String url) at
FileEventReaderService.Services.Logger.EventLogger..ctor(String
source, String logName, String url) at
FileEventReaderService.EventReader..ctor(String sqlServer, String
instance, String integratedSecurityType, String username, String
password, String dataBase) at
FileEventReaderService.EventReaderService.OnStart(String[] args) at
System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object
state)
For more information, see Help and Support Center at
go.microsoft.com/fwlink/….
In my case the problem were with multiple registering the tcp channel, in same instance, so i made a singleton class, and just set client once, and all other time i just called that instance....
using Remoting;
namespace FileEventReaderService.Services.Remotable
{
class SingletonClient
{
private static SingletonClient _instance = new SingletonClient();
private Client _client = null;
public static SingletonClient GetSingletonClient()
{
return _instance;
}
public Client GetClient()
{
return _client;
}
public void SetClientConfiguration(string url)
{
_client=new Client(url);
}
}
}
BTW, if any one need to find the process... he can use this article:
http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c/ download the demo source and use it...
i also edit it in my own way, you can use it: (i did not changed 2 main class 'TcpTable' and 'IpHelper')
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;
using System.Net;
using System.Diagnostics;
using System.Collections;
using System.IO;
namespace FileEventReaderUI.Services.Network
{
class NetworkInformation
{
public ListenerProcessInformation GetListenerProcessInformationByPort(int port)
{
string fileName;
List<string> processModules=new List<string>();
foreach (TcpRow tcpRow in ManagedIpHelper.GetExtendedTcpTable(true))
{
if (tcpRow.LocalEndPoint.Port.ToString(CultureInfo.InvariantCulture).Equals(
port.ToString(CultureInfo.InvariantCulture))
&& tcpRow.State==TcpState.Listen)
{
Process process = Process.GetProcessById(tcpRow.ProcessId);
if (process.ProcessName != "System")
{
foreach (ProcessModule processModule in process.Modules)
{
processModules.Add(processModule.FileName);
}
fileName = Path.GetFileName(process.MainModule.FileName);
}
else
{
//Console.WriteLine(" -- unknown component(s) --"); ProcessModules count=0
//Console.WriteLine(" [{0}]", "System");
fileName = "[System]";
}
return new ListenerProcessInformation(fileName
, processModules.ToArray()
, new IPEndPoint(tcpRow.LocalEndPoint.Address,
tcpRow.LocalEndPoint.Port)
, new IPEndPoint(tcpRow.RemoteEndPoint.Address,
tcpRow.RemoteEndPoint.Port)
, tcpRow.ProcessId
, tcpRow.State);
}
}
return null;
}
}
#region Managed IP Helper API
public class TcpTable : IEnumerable<TcpRow>
{
#region Private Fields
private IEnumerable<TcpRow> tcpRows;
#endregion
#region Constructors
public TcpTable(IEnumerable<TcpRow> tcpRows)
{
this.tcpRows = tcpRows;
}
#endregion
#region Public Properties
public IEnumerable<TcpRow> Rows
{
get { return this.tcpRows; }
}
#endregion
#region IEnumerable<TcpRow> Members
public IEnumerator<TcpRow> GetEnumerator()
{
return this.tcpRows.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this.tcpRows.GetEnumerator();
}
#endregion
}
public class TcpRow
{
#region Private Fields
private IPEndPoint localEndPoint;
private IPEndPoint remoteEndPoint;
private TcpState state;
private int processId;
#endregion
#region Constructors
public TcpRow(IpHelper.TcpRow tcpRow)
{
this.state = tcpRow.state;
this.processId = tcpRow.owningPid;
int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
long localAddress = tcpRow.localAddr;
this.localEndPoint = new IPEndPoint(localAddress, localPort);
int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
long remoteAddress = tcpRow.remoteAddr;
this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
}
#endregion
#region Public Properties
public IPEndPoint LocalEndPoint
{
get { return this.localEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return this.remoteEndPoint; }
}
public TcpState State
{
get { return this.state; }
}
public int ProcessId
{
get { return this.processId; }
}
#endregion
}
public static class ManagedIpHelper
{
#region Public Methods
public static TcpTable GetExtendedTcpTable(bool sorted)
{
List<TcpRow> tcpRows = new List<TcpRow>();
IntPtr tcpTable = IntPtr.Zero;
int tcpTableLength = 0;
if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
{
try
{
tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
{
IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
for (int i = 0; i < table.length; ++i)
{
tcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
}
}
}
finally
{
if (tcpTable != IntPtr.Zero)
{
Marshal.FreeHGlobal(tcpTable);
}
}
}
return new TcpTable(tcpRows);
}
#endregion
}
#endregion
#region P/Invoke IP Helper API
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366073.aspx"/>
/// </summary>
public static class IpHelper
{
#region Public Fields
public const string DllName = "iphlpapi.dll";
public const int AfInet = 2;
#endregion
#region Public Methods
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// </summary>
[DllImport(IpHelper.DllName, SetLastError = true)]
public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);
#endregion
#region Public Enums
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366386.aspx"/>
/// </summary>
public enum TcpTableType
{
BasicListener,
BasicConnections,
BasicAll,
OwnerPidListener,
OwnerPidConnections,
OwnerPidAll,
OwnerModuleListener,
OwnerModuleConnections,
OwnerModuleAll,
}
#endregion
#region Public Structs
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpTable
{
public uint length;
public TcpRow row;
}
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpRow
{
public TcpState state;
public uint localAddr;
public byte localPort1;
public byte localPort2;
public byte localPort3;
public byte localPort4;
public uint remoteAddr;
public byte remotePort1;
public byte remotePort2;
public byte remotePort3;
public byte remotePort4;
public int owningPid;
}
#endregion
}
#endregion
}
and the Entity class i use to fill ...
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
namespace FileEventReaderUI.Services.Network
{
class ListenerProcessInformation
{
private string _fileName;
private string[] _processModules;
private IPEndPoint _localEndPoint;
private IPEndPoint _remoteEndPoint;
private int _processId;
private TcpState _state;
public ListenerProcessInformation(string fileName, string[] processModules, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, int processId, TcpState state)
{
_fileName = fileName;
_processModules = processModules;
_localEndPoint = localEndPoint;
_remoteEndPoint = remoteEndPoint;
_processId = processId;
_state = state;
}
public string FileName
{
get { return _fileName; }
}
public string[] ProcessModules
{
get { return _processModules; }
}
public IPEndPoint LocalEndPoint
{
get { return _localEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return _remoteEndPoint; }
}
public int ProcessId
{
get { return _processId; }
}
public TcpState State
{
get { return _state; }
}
}
}