Abandoned Mutex Exception on a Multithread TCP Server - c#

I am creating a multithread server and I am using mutex to control the sending data, the problem is when a client disconnect all the others clients also disconnect.
This is the server code
using Newtonsoft.Json;
using Pastel;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.AccessControl;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DeepestSwordServer
{
public class Program
{
public static TcpListener server;
public static TcpClient client = new TcpClient();
public static Thread t;
public static Mutex mutex = new Mutex(false, "poligamerMod");
public static List<Connection> list = new List<Connection>();
public static Connection con;
static void Main(string[] args)
{
string ConfigPath = Path.Combine(Environment.CurrentDirectory, "config.json");
if (File.Exists(ConfigPath))
{
Console.WriteLine("Starting Server...".Pastel(Color.FromArgb(165, 229, 250)));
try
{
string json = File.ReadAllText(ConfigPath);
Config config = JsonConvert.DeserializeObject<Config>(json);
Start(config.Ip, config.Port);
}
catch (Exception e)
{
Console.WriteLine($"Failed To Start Server Error: {e.Message}".Pastel(Color.FromArgb(255, 0, 0)));
}
}
else
{
Console.WriteLine("Creating Config File...".Pastel(Color.FromArgb(165, 229, 250)));
Config config = new Config();
config.Ip = "0.0.0.0";
config.Port = 3878;
string json = JsonConvert.SerializeObject(config);
File.Create(ConfigPath).Dispose();
File.WriteAllText(ConfigPath, json);
Console.WriteLine("File Created!".Pastel(Color.FromArgb(58, 255, 0)));
Console.WriteLine("Please see the config.json where is the ip, port and password if needed of the server, you need to restart the server!".Pastel(Color.FromArgb(165, 229, 250)));
Console.ReadLine();
}
}
public static void Start(string ip, int port)
{
Console.WriteLine("Server Ready!".Pastel(Color.FromArgb(58, 255, 0)));
server = new TcpListener(IPAddress.Parse(ip), port);
server.Start();
while (true)
{
client = server.AcceptTcpClient();
con = new Connection();
con.stream = client.GetStream();
con.streamr = new StreamReader(con.stream);
con.streamw = new StreamWriter(con.stream);
con.username = con.streamr.ReadLine();
con.id = con.streamr.ReadLine();
Event #event = new Event();
#event.EventType = EventType.Join;
#event.Username = con.username;
#event.Id = con.id;
string join = JsonConvert.SerializeObject(#event);
foreach (Connection c in list)
{
c.streamw.WriteLine(join);
#event = new Event();
#event.EventType = EventType.Join;
#event.Username = c.username;
#event.Id = c.id;
string newJoin = JsonConvert.SerializeObject(#event);
con.streamw.WriteLine(newJoin);
}
list.Add(con);
#event = new Event();
#event.EventType = EventType.List;
foreach (Connection c in list.ToList())
{
#event.List.Add(c.username, c.id);
}
string playerList = JsonConvert.SerializeObject(#event);
con.streamw.WriteLine(playerList);
Console.WriteLine($"{con.username} with id {con.id} has connected!".Pastel(Color.FromArgb(58, 255, 0)));
t = new Thread(HearConnection);
t.Start();
}
}
public static void HearConnection()
{
Connection hcon = con;
do
{
try
{
foreach (Connection c in list.ToList())
{
mutex.WaitOne();
c.streamw.WriteLine(hcon.streamr.ReadLine());
mutex.ReleaseMutex();
}
}
catch (Exception e)
{
list.Remove(hcon);
Event #event = new Event();
#event.EventType = EventType.Leave;
#event.Username = con.username;
#event.Id = con.id;
string leave = JsonConvert.SerializeObject(#event);
foreach (Connection c in list)
{
c.streamw.WriteLine(leave);
}
Console.WriteLine($"{hcon.username} with id {hcon.id} has disconnected!".Pastel(Color.FromArgb(255, 0, 0)));
Console.WriteLine(e.ToString());
break;
}
} while (true);
}
public struct Connection
{
public NetworkStream stream;
public StreamWriter streamw;
public StreamReader streamr;
public string username;
public string id;
}
}
}
Here is the important parts of the client code
public void Connect()
{
MultiPlayerSubMenu.transform.GetChild(2).gameObject.GetComponent<Button>().enabled = false;
MultiPlayerSubMenu.transform.GetChild(2).GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = "Connecting...";
try
{
client.Connect(IPAddress.Parse(Ip.GetComponent<InputField>().text), Convert.ToInt32(Port.GetComponent<InputField>().text));
if (client.Connected)
{
t = new Thread(Listen);
stream = client.GetStream();
streamw = new StreamWriter(stream);
streamr = new StreamReader(stream);
streamw.AutoFlush = true;
streamw.WriteLine(Username);
streamw.WriteLine(Id);
t.IsBackground = true;
t.Start();
StartCoroutine(Yes());
}
else
{
MultiPlayerSubMenu.transform.GetChild(2).GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = "Cant Connect To Server!";
MultiPlayerSubMenu.transform.GetChild(2).gameObject.GetComponent<Image>().color = Color.red;
StartCoroutine(No());
}
}
catch (Exception e)
{
Logger.LogInfo(e.Message);
MultiPlayerSubMenu.transform.GetChild(2).GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = "Cant Connect To Server!";
MultiPlayerSubMenu.transform.GetChild(2).gameObject.GetComponent<Image>().color = Color.red;
StartCoroutine(No());
}
}
public void Listen()
{
while (client.Connected)
{
try
{
string message = streamr.ReadLine();
DoEvent(message);
Logger.LogInfo(message);
}
catch(Exception e)
{
if (!client.Connected)
{
LostConnection = true;
}
else
{
Logger.LogError(e.ToString());
}
}
}
}
What I want is that the others clients dont disconnect if one client disconnect.

Related

C# Issue sending and receiving data

I know that this is a very discussed topic, but i'm facing a strange behavior from my code.
Making some tests I found that everything goes perfectly for some clients but others simply can't receive and send data through my custom Client design TCPClient based.
I can't confirm if this issue is caused by VPN or NATs connections although many Users can access my server from this connection types.
I' ve been reading about TCPClient and TCPListener in .Net and searching issues like mine but no luck. Everything I got are poor examples.
I will appreciate any help, even book references for network advanced programming.
Here is my code. Most stable up to date
Cliente.cs
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.Linq;
using System.IO.Compression;
namespace netComunicator
{
public class Client:IDisposable
{
int BufferSize { get { return 16384; } }
/// <summary>
/// .NET TcpClient for receive and send methods
/// </summary>
public TcpClient NetClient = new TcpClient();
/// <summary>
/// Externl buffer to store incoming data
/// This buffers get clear when EOS secuence is present on it
/// </summary>
List<byte> ExternBuffer = new List<byte>();
/// <summary>
/// Remote port
/// </summary>
public string Port { get; set; }
/// <summary>
/// MAC address from client
/// </summary>
public string ClientMac { get; set; }
/// <summary>
/// Client IP
/// </summary>
public string ClientIp { get; set; }
/// <summary>
/// Cifrado
/// Use NETSID as public key and his first 128 bits as IV
/// </summary>
private NetCipher Cipher { get; set; }
/// <summary>
/// Shared network session id
/// </summary>
public string NETSID { get; set; }
#region delegados y eventos
public delegate void NoConnection(string noConnectedClient);
public delegate void ObjectDataReceived(object data, Client client);
public delegate void ClientDisconnected(Client client);
public event ClientDisconnected OnClientDisconnected;
public event ObjectDataReceived OnObjectDataReceived;
public event NoConnection OnFailConnectTo;
#endregion
public NetworkStream NetStream;
CancellationTokenSource CTS;
CancellationToken Token;
CancellationTokenSource CancelKAS;
CancellationToken CancelKASToken;
/// <summary>
/// Max lost count of KEEP_ALIVE
/// </summary>
const int MAX_KEEP_ALIVE_COUNT = 30;
/// <summary>
/// Current lost KEEP_ALIVE_SIGNAL
/// </summary>
int CURRENT_KEEP_ALIVE_SIGNAL_COUNT = 0;
public Client(byte[] NETSID)
{
CTS = new CancellationTokenSource();
Token = CTS.Token;
CancelKAS = new CancellationTokenSource();
CancelKASToken = CancelKAS.Token;
ClientMac = GetMac();
if (NETSID != null)
{
Cipher = new NetCipher(NETSID);
this.NETSID = new Guid(NETSID).ToString();
}
}
public void StartClient()
{
try
{
Task.Factory.StartNew(() => Receive(), Token);
}
catch { }
}
public void StopClient()
{
CTS.Cancel();
}
public void StartKeepAliveSignal()
{
Task.Factory.StartNew(() =>
{
while (!CancelKASToken.IsCancellationRequested)
{
if (CURRENT_KEEP_ALIVE_SIGNAL_COUNT == MAX_KEEP_ALIVE_COUNT)
{
OnClientDisconnected?.BeginInvoke(this, null, null);
Dispose();
}
Send("KEEP_ALIVE");
CURRENT_KEEP_ALIVE_SIGNAL_COUNT++;
Thread.Sleep(1000);
}
}, CancelKASToken);
}
public void StoptKeepAliveSignal()
{
CancelKAS.Cancel();
}
static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
if (ip.AddressFamily == AddressFamily.InterNetwork)
return ip.ToString();
throw new Exception("No network adapters with an IPv4 address in the system!");
}
string GetMac()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
var mac = nics.Where(n => n.OperationalStatus == OperationalStatus.Up).FirstOrDefault();
if (mac != null)
return mac.GetPhysicalAddress().ToString();
return "";
}
void CloseConnection()
{
NetClient.Close();
}
public void Dispose()
{
try
{
StoptKeepAliveSignal();
StopClient();
CloseConnection();
}
catch{ }
}
async public Task<bool> Connect(string ip, int port, bool initKAS = true)
{
return await Task.Factory.StartNew(() =>
{
try
{
NetClient.Connect(ip, port);
Guid guid = new Guid(NETSID);
if (NetStream == null)
{
NetStream = NetClient.GetStream();
Cipher = new NetCipher(guid.ToByteArray());
}
List<byte> initdata = new List<byte>();
initdata.AddRange(NetComTools.wellcomeMsg);
initdata.AddRange(System.Text.Encoding.ASCII.GetBytes(ClientMac));
initdata.AddRange(guid.ToByteArray());
NetStream.Write(initdata.ToArray(), 0, initdata.Count);
StartClient();
// if required KEEP_ALIVE_SIGNAL on
if (initKAS)
StartKeepAliveSignal();
ClientIp = ip;
return true;
}
catch
{
// Notificar que no se pudo establecer conexion
OnFailConnectTo?.Invoke(ip);
}
return false;
});
}
public void Receive()
{
while (!Token.IsCancellationRequested)
{
try
{
byte[] buff = new byte[BufferSize];
int bytesReaded = NetStream.Read(buff, 0, buff.Length);
byte[] bytesFromBuffer = buff.Take(bytesReaded).ToArray();
CURRENT_KEEP_ALIVE_SIGNAL_COUNT = 0;
ExternBuffer.AddRange(bytesFromBuffer);
// Determine if current received bytes have End Of Secuence byte array
bool isEOS = IsEndOfSecuence(ExternBuffer);
if (isEOS)
{
// Secuence separator takes inside EOS and passing ExternBuffer
// split current buffer in N subsecuences.
// This because in one buffer read, can be more than one message delimited by EOS
List<byte[]> secuences = SecuenceSeparator(ExternBuffer);
ExternBuffer.Clear();
foreach (byte[] secuence in secuences)
{
byte[] decompress = Decompress(secuence);
byte[] decipher = Cipher.Decrypt(decompress);
object data = Serializer.Deserialize(decipher);
OnObjectDataReceived?.BeginInvoke(data, this, null, null);
}
}
}
catch
{
Dispose();
OnClientDisconnected?.Invoke(this);
return;
}
Thread.Sleep(10);
}
}
/// <summary>
/// If bytes[] have an EOS secuence return true
/// </summary>
bool IsEndOfSecuence(byte[] bytes)
{
int secuencelen = bytes.Length - 1;
int checkSum = NetComTools.EOS.Length - 1;
int EOSLen = checkSum;
int trys = 0;
for (int i = secuencelen; i >= 0; i--)
{
if (trys <= EOSLen)
{
if (checkSum == 0)
return true;
if (bytes[i] == NetComTools.EOS[checkSum])
checkSum--;
else
checkSum = NetComTools.EOS.Length - 1;
}
else
return false;
trys++;
}
return false;
}
bool IsEndOfSecuence(List<byte> bytes)
{
int secuencelen = bytes.Count - 1;
int checkSum = NetComTools.EOS.Length - 1;
int EOSLen = checkSum;
int trys = 0;
for (int i = secuencelen; i >= 0; i--)
{
if (trys <= EOSLen)
{
if (checkSum == 0)
return true;
if (bytes[i] == NetComTools.EOS[checkSum])
checkSum--;
else
checkSum = NetComTools.EOS.Length - 1;
}
else
return false;
trys++;
}
return false;
}
List<byte[]> SecuenceSeparator(byte[] data)
{
List<byte[]> subsecuences = new List<byte[]>();
List<byte> externBuff = new List<byte>(data);
int inc = 0;
int secuencelen = externBuff.Count;
int lastpos = 0;
//40 = 15 + datos, 5 + eos, 15 + datos, 5 + eos
for (int i = 0; i < secuencelen; i++)
{
if (externBuff[i] == NetComTools.EOS[inc])
{
inc++;
if (inc == NetComTools.EOS.Length)
{
List<byte> sub_nsecuence = new List<byte>();
int elements = i + 1 - lastpos - NetComTools.EOS.Length;
byte[] matchsecuence = new byte[elements];
externBuff.CopyTo(lastpos, matchsecuence, 0, elements);
sub_nsecuence.AddRange(matchsecuence);
subsecuences.Add(sub_nsecuence.ToArray());
inc = 0;
lastpos = i + 1;
}
}
else
inc = 0;
}
return subsecuences;
}
List<byte[]> SecuenceSeparator(List<byte> externBuff)
{
List<byte[]> subsecuences = new List<byte[]>();
int inc = 0;
int secuencelen = externBuff.Count;
int lastpos = 0;
for (int i = 0; i < secuencelen; i++)
{
if (externBuff[i] == NetComTools.EOS[inc])
{
inc++;
if (inc == NetComTools.EOS.Length)
{
List<byte> sub_nsecuence = new List<byte>();
int elements = i + 1 - lastpos - NetComTools.EOS.Length;
byte[] matchsecuence = new byte[elements];
externBuff.CopyTo(lastpos, matchsecuence, 0, elements);
sub_nsecuence.AddRange(matchsecuence);
subsecuences.Add(sub_nsecuence.ToArray());
inc = 0;
lastpos = i + 1;
}
}
else
inc = 0;
}
return subsecuences;
}
public void Send(object data)
{
try
{
byte[] objDatabyte = Serializer.Serialize(data);
byte[] cipher = Cipher.Encrypt(objDatabyte);
byte[] compressed = Compress(cipher);
NetStream.Write(compressed, 0, compressed.Length);
NetStream.Write(NetComTools.EOS, 0, NetComTools.EOS.Length);
}
catch
{
OnClientDisconnected?.Invoke(this);
Dispose();
}
}
public static byte[] Compress(byte[] raw)
{
using (MemoryStream msw = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(msw, CompressionMode.Compress))
gzip.Write(raw, 0, raw.Length);
return msw.ToArray();
}
}
public static byte[] Decompress(byte[] gzipraw)
{
using (GZipStream msw = new GZipStream(new MemoryStream(gzipraw), CompressionMode.Decompress))
{
using (MemoryStream ms = new MemoryStream())
{
int readed;
while ((readed = msw.ReadByte()) != -1)
ms.WriteByte((byte)readed);
return ms.ToArray();
}
}
}
}
static class Serializer
{
public static byte[] Serialize(object anySerializableObject)
{
using (var memoryStream = new MemoryStream())
{
(new BinaryFormatter()).Serialize(memoryStream, anySerializableObject);
return memoryStream.ToArray();
}
}
public static object Deserialize(byte[] message)
{
using (var memoryStream = new MemoryStream(message))
{
BinaryFormatter b = new BinaryFormatter();
memoryStream.Position = 0;
return b.Deserialize(memoryStream);
}
}
}
}
Server.cs
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;
using System.Linq;
namespace netComunicator
{
public class Server
{
/// <summary>
/// Connected Clients
/// </summary>
public ConcurrentBag<Client> Clients = new ConcurrentBag<Client>();
/// <summary>
/// .NET TcpListenet
/// </summary>
public TcpListener Host;
CancellationTokenSource CTS;
CancellationToken Token;
#region Delegados y Eventos
public delegate void ClientConnected(Client client);
public delegate void ClientDisconnected(Client client);
public event ClientConnected OnClientConnected;
public event ClientDisconnected OnClientDisconnected;
#endregion
public Server(int port)
{
CTS = new CancellationTokenSource();
Token = CTS.Token;
try
{
Host = new TcpListener(IPAddress.Parse(NetComTools.thisClientIP), port);
Host.Start();
try { Task.Factory.StartNew(() => AcceptIncoming(), Token); } catch (Exception ex) {
throw ex;
}
}
catch (Exception ec)
{
throw ec;
}
}
public void SendTo(Client client, object data)
{
Client cl = Clients.Where(c => c.Equals(client)).FirstOrDefault();
cl?.Send(data);
}
public void SendAll(object data)
{
Task.Factory.StartNew(() =>
{
foreach (Client client in Clients)
client.Send(data);
});
}
void AcceptIncoming()
{
while (!Token.IsCancellationRequested)
{
try
{
AsyncCallback acb = new AsyncCallback(PerformConnection);
Host.BeginAcceptSocket(acb, null);
Thread.Sleep(10);
}
catch (Exception ex)
{
throw ex;
}
}
}
void PerformConnection(IAsyncResult res)
{
TcpClient tempClient = null;
try
{
tempClient = Host.EndAcceptTcpClient(res);
NetworkStream ns;
ns = tempClient.GetStream();
byte[] initData = new byte[NetComTools.wellcomeMsg.Length + 28];
ns.Read(initData, 0, initData.Length);
byte[] wellcome = new byte[NetComTools.wellcomeMsg.Length];
byte[] mac = new byte[12];
byte[] netsidfromclient = new byte[16];
List<byte> ini = new List<byte>(initData);
ini.CopyTo(0, wellcome, 0, 4);
ini.CopyTo(4, mac, 0, 12);
ini.CopyTo(16, netsidfromclient, 0, 16);
if (WellcomeOk(wellcome))
{
Client newClient = new Client(netsidfromclient)
{
ClientIp = tempClient.Client.RemoteEndPoint.ToString().Split(':')[0],
Port = tempClient.Client.RemoteEndPoint.ToString().Split(':')[1],
NetStream = ns,
ClientMac = System.Text.Encoding.ASCII.GetString(mac),
};
Clients.Add(newClient);
newClient.NetClient = tempClient;
newClient.OnClientDisconnected += newClient_OnClientDisconnected;
newClient.StartClient();
OnClientConnected?.BeginInvoke(newClient, null, null);
}
else
tempClient.Close();
}
catch {if( tempClient != null) tempClient.Close(); return; }
}
bool WellcomeOk(byte[] wellcomeFromNet)
{
if (wellcomeFromNet.Length != NetComTools.wellcomeMsg.Length)
return false;
else
{
for (int i = 0; i < wellcomeFromNet.Length; i++)
if (wellcomeFromNet[i] != NetComTools.wellcomeMsg[i])
return false;
}
return true;
}
void newClient_OnClientDisconnected(Client client)
{
client.OnClientDisconnected -= newClient_OnClientDisconnected;
Clients = RemoveClientFromList(client);
OnClientDisconnected?.Invoke(client);
}
ConcurrentBag<Client> RemoveClientFromList(Client client)
{
ConcurrentBag<Client> Acl = new ConcurrentBag<Client>();
return new ConcurrentBag<Client>(Clients.Where(c => c != client));
}
public void StopListener()
{
Host.Stop();
CTS.Cancel();
}
}
}

Windows Form Application failed with .NET Remoting Service

I am trying to insert data into database by using windows from application . I hosted it into console application . I am using .net remoting to invoke the method . My host is running without any problem and i also can run the windows form application without any problem . But problem is when i clicked the submit button to insert data i got error.I do not know why i am getting this error .
Exception thrown: 'System.NullReferenceException' in mscorlib.dll
Additional information: Object reference not set to an instance of an object. occurred
Here is the Interface .
namespace IHelloRemotingService
{
public interface IHelloRemotingService
{
void Insert(string Name, string Address, string Email, string Mobile)
}
}
Here is the Implementation of the interface ..
public class HelloRemotingService : MarshalByRefObject , IHelloRemotingService.IHelloRemotingService
{
public void Insert(string Name, string Address, string Email, string Mobile)
{
string constr = ConfigurationManager.ConnectionStrings["StudentConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("AddNewStudent", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", Name);
cmd.Parameters.AddWithValue("#Address", Address);
cmd.Parameters.AddWithValue("#EmailID", Email);
cmd.Parameters.AddWithValue("#Mobile", Mobile);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
}
Code for Hosting service ....
namespace RemotingServiceHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" .NET Remoting Test Server");
Console.WriteLine(" *************************");
Console.WriteLine();
try
{
StartServer();
Console.WriteLine("Server started");
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine("Server.Main exception: " + ex);
}
Console.WriteLine("Press <ENTER> to exit.");
Console.ReadLine();
StopServer();
}
static void StartServer()
{
RegisterBinaryTCPServerChannel(500);
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
RemotingConfiguration.RegisterWellKnownServiceType(typeof(HelloRemotingService.HelloRemotingService),
"Insert.rem",
WellKnownObjectMode.Singleton);
}
static void StopServer()
{
foreach (IChannel channel in ChannelServices.RegisteredChannels)
{
try
{
ChannelServices.UnregisterChannel(channel);
}
catch (Exception ex)
{
Console.WriteLine("Server.StopServer exception: " + ex);
}
}
}
static void RegisterBinaryTCPServerChannel(int port, string name = "tcp srv")
{
IServerChannelSinkProvider firstServerProvider;
IClientChannelSinkProvider firstClientProvider;
var channelProperties = new Hashtable();
channelProperties["typeFilterLevel"] = TypeFilterLevel.Full;
channelProperties["machineName"] = Environment.MachineName;
channelProperties["port"] = port;
// create server format provider
var serverFormatProvider = new BinaryServerFormatterSinkProvider(null, null); // binary formatter
serverFormatProvider.TypeFilterLevel = TypeFilterLevel.Full;
firstServerProvider = serverFormatProvider;
// create client format provider
var clientProperties = new Hashtable();
clientProperties["typeFilterLevel"] = TypeFilterLevel.Full;
var clientFormatProvider = new BinaryClientFormatterSinkProvider(clientProperties, null);
firstClientProvider = clientFormatProvider;
TcpChannel tcp = new TcpChannel(channelProperties, firstClientProvider, firstServerProvider);
ChannelServices.RegisterChannel(tcp, false);
}
}
}
Code for windows form application ..
namespace HelloRemotingServiceClient
{
public partial class InsertStudentData : Form
{
public InsertStudentData()
{
InitializeComponent();
RegisterBinaryTcpClientChannel();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
var remService = (IHelloRemotingService.IHelloRemotingService)Activator.GetObject(typeof(IHelloRemotingService.IHelloRemotingService), "tcp://localhost:500/Insert.rem");
remService.Insert(textName.Text, textAddress.Text, textEmail.Text, textBox1.Text);
label5.Text = "Recored Inserted Successfully";
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void RegisterBinaryTcpClientChannel(string name = "tcp client")
{
IClientChannelSinkProvider firstClientProvider;
IServerChannelSinkProvider firstServerProvider;
var channelProperties = new Hashtable();
channelProperties["name"] = name;
channelProperties["typeFilterLevel"] = TypeFilterLevel.Full;
channelProperties["machineName"] = Environment.MachineName;
channelProperties["port"] = 0; // auto
// create client format provider
var clientProperties = new Hashtable();
clientProperties["typeFilterLevel"] = TypeFilterLevel.Full;
var clientFormatProvider = new BinaryClientFormatterSinkProvider(clientProperties, null);
firstClientProvider = clientFormatProvider;
// create server format provider
var serverFormatProvider = new BinaryServerFormatterSinkProvider(null, null);
serverFormatProvider.TypeFilterLevel = TypeFilterLevel.Full;
firstServerProvider = serverFormatProvider;
TcpChannel tcp = new TcpChannel(channelProperties, firstClientProvider, firstServerProvider);
ChannelServices.RegisterChannel(tcp, false);
}
}
}
Design of the form ..
Here is the screen shot of errors messages .
The text boxes are able to catch the values but why its throwing this error ?
Here is a working project. You did not configure the formatter.
SharedLib Project:
namespace IHelloRemotingService
{
public interface IHelloRemotingService
{
void Insert(string Name, string Address, string Email, string Mobile);
}
}
Server Console Project:
namespace Server
{
public class HelloRemotingService : MarshalByRefObject, IHelloRemotingService.IHelloRemotingService
{
public HelloRemotingService()
{
}
public void Insert(string Name, string Address, string Email, string Mobile)
{
Console.WriteLine("HelloRemotingService.Insert called");
}
public override object InitializeLifetimeService()
{
return null; // manage lifetime by myself
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" .NET Remoting Test Server");
Console.WriteLine(" *************************");
Console.WriteLine();
try
{
StartServer();
Console.WriteLine("Server started");
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine("Server.Main exception: " + ex);
}
Console.WriteLine("Press <ENTER> to exit.");
Console.ReadLine();
StopServer();
}
static void StartServer()
{
RegisterBinaryTCPServerChannel(500);
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
RemotingConfiguration.RegisterWellKnownServiceType(typeof(HelloRemotingService),
"Insert.rem",
WellKnownObjectMode.Singleton);
}
static void StopServer()
{
foreach (IChannel channel in ChannelServices.RegisteredChannels)
{
try
{
ChannelServices.UnregisterChannel(channel);
}
catch(Exception ex)
{
Console.WriteLine("Server.StopServer exception: " + ex);
}
}
}
static void RegisterBinaryTCPServerChannel(int port, string name = "tcp srv")
{
IServerChannelSinkProvider firstServerProvider;
IClientChannelSinkProvider firstClientProvider;
var channelProperties = new Hashtable();
channelProperties["typeFilterLevel"] = TypeFilterLevel.Full;
channelProperties["machineName"] = Environment.MachineName;
channelProperties["port"] = port;
// create server format provider
var serverFormatProvider = new BinaryServerFormatterSinkProvider(null, null); // binary formatter
serverFormatProvider.TypeFilterLevel = TypeFilterLevel.Full;
firstServerProvider = serverFormatProvider;
// create client format provider
var clientProperties = new Hashtable();
clientProperties["typeFilterLevel"] = TypeFilterLevel.Full;
var clientFormatProvider = new BinaryClientFormatterSinkProvider(clientProperties, null);
firstClientProvider = clientFormatProvider;
TcpChannel tcp = new TcpChannel(channelProperties, firstClientProvider, firstServerProvider);
ChannelServices.RegisterChannel(tcp, false);
}
}
}
Client WinForms Project:
namespace Client
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
RegisterBinaryTcpClientChannel();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (MainForm form = new MainForm())
{
Application.Run(form);
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
foreach (IChannel channel in ChannelServices.RegisteredChannels)
{
try
{
ChannelServices.UnregisterChannel(channel);
}
catch (Exception ex)
{
Debug.WriteLine("Client.Dispose exception: " + ex);
}
}
if (components != null)
components.Dispose();
}
base.Dispose(disposing);
}
private void _btnAccessServer_Click(object sender, EventArgs e)
{
try
{
var remService = (IHelloRemotingService.IHelloRemotingService)Activator.GetObject(typeof(IHelloRemotingService.IHelloRemotingService), "tcp://localhost:500/Insert.rem");
remService.Insert("MyName", "MyAddress", "MyEmail", "MyMobile");
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void RegisterBinaryTcpClientChannel(string name = "tcp client")
{
IClientChannelSinkProvider firstClientProvider;
IServerChannelSinkProvider firstServerProvider;
var channelProperties = new Hashtable();
channelProperties["name"] = name;
channelProperties["typeFilterLevel"] = TypeFilterLevel.Full;
channelProperties["machineName"] = Environment.MachineName;
channelProperties["port"] = 0; // auto
// create client format provider
var clientProperties = new Hashtable();
clientProperties["typeFilterLevel"] = TypeFilterLevel.Full;
var clientFormatProvider = new BinaryClientFormatterSinkProvider(clientProperties, null);
firstClientProvider = clientFormatProvider;
// create server format provider
var serverFormatProvider = new BinaryServerFormatterSinkProvider(null, null);
serverFormatProvider.TypeFilterLevel = TypeFilterLevel.Full;
firstServerProvider = serverFormatProvider;
TcpChannel tcp = new TcpChannel(channelProperties, firstClientProvider, firstServerProvider);
ChannelServices.RegisterChannel(tcp, false);
}
}
}

Unity/C# - Connect to Unity Server on another computer

I'm currently writing the Networking backend for a game I'm creating in Unity. The problem I'm facing is connecting to my server on another computer (on the same local network). I'm extremely new to uNet and what it entails, so the help is very appreciated.
I've followed a few tutorials, but none have fixed the problem that I've been facing. There's currently no connection at all coming through to the server. I've initialised the server, created sockets, used Network.Listen() to listen to packets coming through the port - but nothing quite yet.
This is a test project that I'm doing before implementing into the game, so sorry for the not-so-clean code.
The IP's are specified in Inspector, but used "127.0.0.1" to preset it. Sorry for the confusion!
Here's the client-side code:
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class ClientConnector : NetworkManager
{
NetworkClient m_client;
public GameObject screenCanvas;
bool socketConnection = false;
bool serverConnection = false;
bool connectingToSocket = false;
bool connectingToServer = false;
bool connectedToServer = false;
public int socketConnectionPort = 8888;
public int serverConnectionPort = 8899;
public string connectionIP = "127.0.0.1";
public int maxConnectionsNumber = 10;
int reliableChannelID;
int socketID;
int socketConnectionID;
int serverConnectionID;
void Start ()
{
NetworkTransport.Init();
m_client = new NetworkClient();
if (SetupConnection())
{
ConnectSocket();
}
if (socketConnection)
{
ConnectServer();
}
}
void OnApplicationQuit()
{
NetworkTransport.Shutdown();
}
public void ConnectSocket()
{
connectingToSocket = true;
byte error;
socketConnectionID = NetworkTransport.Connect(socketID, connectionIP, socketConnectionPort, 0, out error);
if (socketConnectionID != 0)
{
socketConnection = true;
connectingToSocket = false;
}
}
public void ConnectServer()
{
connectingToServer = true;
byte error;
serverConnectionID = NetworkTransport.Connect(socketID, connectionIP, serverConnectionPort, 0, out error);
if (!ReferenceEquals(socketID, 0))
{
serverConnection = true;
connectedToServer = true;
connectingToServer = false;
SendSocketMessage();
}
}
bool SetupConnection()
{
ConnectionConfig config = new ConnectionConfig();
reliableChannelID = config.AddChannel(QosType.Reliable);
HostTopology topology = new HostTopology(config, maxConnectionsNumber);
socketID = NetworkTransport.AddHost(topology, socketConnectionPort);
if (!ReferenceEquals(client, null))
{
client.RegisterHandler(MsgType.Connect, OnConnected);
}
if (ReferenceEquals(socketID, 0))
{
Debug.Log("Socket open. Socket ID is: " + socketConnectionID);
return true;
}
else
{
return false;
}
}
void Update ()
{
ReceiveAndHandlePacket();
}
void ReceiveAndHandlePacket()
{
int recChannelID;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType networkEvent = NetworkTransport.Receive(out socketID, out socketConnectionID, out recChannelID, recBuffer, bufferSize, out dataSize, out error);
switch (networkEvent)
{
case NetworkEventType.Nothing:
{
Debug.Log("No packets!");
break;
}
case NetworkEventType.ConnectEvent:
{
break;
}
case NetworkEventType.DataEvent:
{
Stream stream = new MemoryStream(recBuffer);
bufferSize = (int)stream.Position;
BinaryFormatter formatter = new BinaryFormatter();
string data = formatter.Deserialize(stream) as string;
Debug.Log("Received Packet from Server saying: " + data);
break;
}
case NetworkEventType.DisconnectEvent:
{
Debug.Log("Disconnected.");
break;
}
}
}
void SendSocketMessage()
{
byte error;
byte[] buffer = new byte[1024];
Stream stream = new MemoryStream(buffer);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, "Connecting from Client.");
int bufferSize = (int)stream.Position;
NetworkTransport.Send(socketID, socketConnectionID, reliableChannelID, buffer, bufferSize, out error);
}
void OnConnected(NetworkMessage netMsg)
{
Debug.Log("Connected to Socket on " + connectionIP);
}
}
and here is the server-side code:
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class ServerControl : NetworkManager
{
public GameObject connectionsScreen;
public int maxConnectables;
public int socketConnectionPort = 8888;
public string socketConnectionIP = "127.0.0.1";
public int serverConnectionPort = 8899;
bool useNat;
List<NetworkClient> connections = new List<NetworkClient>();
bool serverInitialized;
int channelID;
int socketID;
int connectionID;
void Start()
{
useNat = !Network.HavePublicAddress();
NetworkTransport.Init();
if (SetupSocket())
{
InitializePeerServer();
}
}
void Update()
{
ReceiveAndHandlePackets();
}
void OnApplicationQuit()
{
NetworkTransport.Shutdown();
}
public bool SetupSocket()
{
ConnectionConfig config = new ConnectionConfig();
channelID = config.AddChannel(QosType.Reliable);
HostTopology topology = new HostTopology(config, maxConnections);
socketID = NetworkTransport.AddHost(topology);
byte error;
connectionID = NetworkTransport.Connect(socketID, socketConnectionIP, socketConnectionPort, 0, out error);
if (connectionID != 0)
{
Debug.Log("Socket open on: " + socketConnectionPort + " with IP: " + socketConnectionIP);
return true;
}
else
return false;
}
public void InitializePeerServer()
{
NetworkConnectionError serverStatus;
serverStatus = Network.InitializeServer(maxConnectables, serverConnectionPort, useNat);
Network.Listen(serverConnectionPort);
switch (serverStatus)
{
case NetworkConnectionError.NoError:
{
serverInitialized = true;
break;
}
default:
{
serverInitialized = false;
break;
}
}
}
public void ReceiveAndHandlePackets()
{
int recChannelID;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType networkEvent = NetworkTransport.Receive(out socketID, out connectionID, out recChannelID, recBuffer, bufferSize, out dataSize, out error);
switch (networkEvent)
{
case NetworkEventType.Nothing:
connectionsScreen.transform.GetChild(6).GetComponent<Text>().text = "Message: \nNo packets!";
break;
case NetworkEventType.ConnectEvent:
{
Debug.Log("Incoming connection.");
break;
}
case NetworkEventType.DataEvent:
{
Stream stream = new MemoryStream(recBuffer);
bufferSize = (int)stream.Position;
BinaryFormatter formatter = new BinaryFormatter();
string data = formatter.Deserialize(stream) as string;
Debug.Log("Received packet, saying: " + data);
connectionsScreen.transform.GetChild(6).GetComponent<Text>().text = "Message Received: " + data;
break;
}
case NetworkEventType.DisconnectEvent:
{
Debug.Log("Disconnected.");
break;
}
}
}
public override void OnClientConnect(NetworkConnection conn)
{
base.OnClientConnect(conn);
NetworkClient client = new NetworkClient(conn);
connections.Add(client);
Debug.Log("New connection from " + conn.address);
}
}
Any and all help is very greatly appreciated!
Thank you!

Transmit xml serialized objects thru named pipe (without WCF)

i want to send specific objects thru a simple named pipe. I think the receiver does not recognize the cut between two sent objects. In the result, i get an xml serialization error. Here is my code:
Server process:
using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Xml.Serialization;
namespace NamedPipe
{
class ProgramServer
{
static void Main(string[] args)
{
NamedPipeServerStream server;
server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
Console.WriteLine("Start loop. ");
Thread.Sleep(1000);
while (true)
{
XmlSerializer receiver = new XmlSerializer(typeof(PayLoad));
object testobj = receiver.Deserialize(reader);
Console.WriteLine("Testobject: " + ((PayLoad)(testobj)).name + ((PayLoad)(testobj)).count);
}
}
}
}
Client process:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace NamedPipe
{
class ProgramClient
{
static void Main(string[] args)
{
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
client.Connect();
StreamReader reader = new StreamReader(client);
while (true)
{
StreamWriter writer = new StreamWriter(client);
PayLoad test = new PayLoad
()
{
name = "Test",
count = 42
};
XmlSerializer sendSerializer = new XmlSerializer(typeof(PayLoad));
sendSerializer.Serialize(writer, test);
}
}
}
}
I have tried recently using NamedPipes without WCF. You can look into this code which might give you some idea. Here, Client is enabled with Callback functionality so server can callback the client.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
const string PIPE_NAME = "testPipeName33";
const string OBJECT_NAME = "test";
const string CALLBACK_PIPE_NAME = "testPipeName34";
const string CALLBACK_OBJECT_NAME = "testclient";
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if ((args.Length == 0 || args[0] == "s"))
{
try
{
IPCRegistration.RegisterServer(PIPE_NAME,OBJECT_NAME);
}
catch (RemotingException)
{
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject),PIPE_NAME,OBJECT_NAME);
remoteObject.OnNewProcessStarted("test");
Application.Exit();
return;
}
MessageBox.Show("Server:" + Process.GetCurrentProcess().Id);
Process.Start(Application.ExecutablePath, "c");
Application.Run(new Form1("Server"));
}
else
{
IsClient = true;
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), PIPE_NAME, OBJECT_NAME);
IPCRegistration.RegisterServer(CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME); // Here Client will listen on this channel.
remoteObject.SetOnNewProcessStarted(OnNewProcessStarted,Process.GetCurrentProcess().Id.ToString());
MessageBox.Show("Client:" + Process.GetCurrentProcess().Id);
Application.Run(new Form1("Client"));
}
}
static RemoteObject remoteObject;
static bool IsClient = false;
static bool OnNewProcessStarted(string commandLine)
{
MessageBox.Show("saved:"+commandLine+" Currrent:"+Process.GetCurrentProcess().Id);
MessageBox.Show("Is Client : " + IsClient);//problem here, IsClient should be true
return true;
}
}
public delegate bool OnNewProcessStartedDelegate(string text);
internal class RemoteObject : MarshalByRefObject
{
public OnNewProcessStartedDelegate OnNewProcessStartedHandler;
public string value;
public bool isCallBack = false;
const string PIPE_NAME = "testPipeName33";
const string OBJECT_NAME = "test";
const string CALLBACK_PIPE_NAME = "testPipeName34";
const string CALLBACK_OBJECT_NAME = "testclient";
RemoteObject remoteObject;
public bool OnNewProcessStarted(string commandLine)
{
if (!isCallBack)
{
remoteObject.isCallBack = true;
return remoteObject.OnNewProcessStarted(commandLine);
}
if (OnNewProcessStartedHandler != null)
return OnNewProcessStartedHandler(value);
return false;
}
public void SetOnNewProcessStarted(OnNewProcessStartedDelegate onNewProcessStarted,string value)
{
this.value = value;
OnNewProcessStartedHandler = onNewProcessStarted;
if (!isCallBack)
{
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME);
remoteObject.isCallBack = true;
remoteObject.SetOnNewProcessStarted(onNewProcessStarted, Process.GetCurrentProcess().Id.ToString());
}
}
public override object InitializeLifetimeService()
{
return null;
}
}
internal class IPCRegistration
{
public static RemoteObject RegisterClient(Type remoteObject,string PIPE_NAME,string OBJECT_NAME)
{
IpcClientChannel chan = new IpcClientChannel();
ChannelServices.RegisterChannel(chan, false);
RemoteObject remoteObjectInstance = (RemoteObject)Activator.GetObject(remoteObject,
string.Format("ipc://{0}/{1}", PIPE_NAME, OBJECT_NAME));
return remoteObjectInstance;
}
public static void RegisterServer(string pipeName, string objectName)
{
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IpcServerChannel chan = new IpcServerChannel("", pipeName, serverProvider);
ChannelServices.RegisterChannel(chan, false);
RemotingServices.Marshal(new RemoteObject(), objectName);
}
}

Lync API: How to send instant message to contact by email address?

I have the email address of a Lync user and want to send him an instant message.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
namespace Build_Server_Lync_Notifier
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: bsln.exe <uri> <message>");
return;
}
LyncClient client = Microsoft.Lync.Model.LyncClient.GetClient();
Contact contact = client.ContactManager.GetContactByUri(args[0]);
Conversation conversation = client.ConversationManager.AddConversation();
conversation.AddParticipant(contact);
Dictionary<InstantMessageContentType, String> messages = new Dictionary<InstantMessageContentType, String>();
messages.Add(InstantMessageContentType.PlainText, args[1]);
InstantMessageModality m = (InstantMessageModality) conversation.Modalities[ModalityTypes.InstantMessage];
m.BeginSendMessage(messages, null, messages);
//Console.Read();
}
}
}
Screenshot
Link to large screenshot: http://i.imgur.com/LMHEF.png
As you can see in this screenshot, my program doesn't really seem to work, even though I'm able to manually search up the contact and send an instant message manually.
I also tried using ContactManager.BeginSearch() instead of ContactManager.GetContactByUri(), but got the same result (you can see in the screenshot): http://pastie.org/private/o9joyzvux4mkhzsjw1pioa
Ok, so I got it working now. Got it in a working state, although I need to do some serious refactoring.
Program.cs
using System;
namespace Build_Server_Lync_Notifier
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: bsln.exe <uri> <message>");
return;
}
LyncManager lm = new LyncManager(args[0], args[1]);
while (!lm.Done)
{
System.Threading.Thread.Sleep(500);
}
}
}
}
LyncManager.cs
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
using System;
using System.Collections.Generic;
namespace Build_Server_Lync_Notifier
{
class LyncManager
{
private string _uri;
private string _message;
private LyncClient _client;
private Conversation _conversation;
private bool _done = false;
public bool Done
{
get { return _done; }
}
public LyncManager(string arg0, string arg1)
{
_uri = arg0;
_message = arg1;
_client = Microsoft.Lync.Model.LyncClient.GetClient();
_client.ContactManager.BeginSearch(
_uri,
SearchProviders.GlobalAddressList,
SearchFields.EmailAddresses,
SearchOptions.ContactsOnly,
2,
BeginSearchCallback,
new object[] { _client.ContactManager, _uri }
);
}
private void BeginSearchCallback(IAsyncResult r)
{
object[] asyncState = (object[]) r.AsyncState;
ContactManager cm = (ContactManager) asyncState[0];
try
{
SearchResults results = cm.EndSearch(r);
if (results.AllResults.Count == 0)
{
Console.WriteLine("No results.");
}
else if (results.AllResults.Count == 1)
{
ContactSubscription srs = cm.CreateSubscription();
Contact contact = results.Contacts[0];
srs.AddContact(contact);
ContactInformationType[] contactInformationTypes = { ContactInformationType.Availability, ContactInformationType.ActivityId };
srs.Subscribe(ContactSubscriptionRefreshRate.High, contactInformationTypes);
_conversation = _client.ConversationManager.AddConversation();
_conversation.AddParticipant(contact);
Dictionary<InstantMessageContentType, String> messages = new Dictionary<InstantMessageContentType, String>();
messages.Add(InstantMessageContentType.PlainText, _message);
InstantMessageModality m = (InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage];
m.BeginSendMessage(messages, BeginSendMessageCallback, messages);
}
else
{
Console.WriteLine("More than one result.");
}
}
catch (SearchException se)
{
Console.WriteLine("Search failed: " + se.Reason.ToString());
}
_client.ContactManager.EndSearch(r);
}
private void BeginSendMessageCallback(IAsyncResult r)
{
_conversation.End();
_done = true;
}
}
}
Try Below Code its working Fine For me
protected void Page_Load(object sender, EventArgs e)
{
SendLyncMessage();
}
private static void SendLyncMessage()
{
string[] targetContactUris = {"sip:xxxx#domain.com"};
LyncClient client = LyncClient.GetClient();
Conversation conv = client.ConversationManager.AddConversation();
foreach (string target in targetContactUris)
{
conv.AddParticipant(client.ContactManager.GetContactByUri(target));
}
InstantMessageModality m = conv.Modalities[ModalityTypes.InstantMessage] as InstantMessageModality;
m.BeginSendMessage("Test Message", null, null);
}

Categories