In my HoloLens2 application sometimes the UDP-Package-receive rate drops instantly from 40 packages per second to 0-2 packages per second and stays there (size of packages between 2000 byte and 60000 byte. The application is made with Unity3d and .Net Sockets for networking. This behaviour sometimes happens straight from application startup, sometimes after 30 minutes, so basically quiet random. Even Restarting HoloLens2 doesn´t help in such a situation. The application logs no exception or error messages. On my Unity-Editor the Application can handle the network traffic without any problem.
It feels like some Network buffer got stuffend and drops all packages so did I miss some Cleanup command in my Networking-Code or is there another way to face Receive-Overload in my code?
Or is HoloLens2 somehow limited in it´s Bandwith when running via Ethernet (and not Wifi)?
At the same time my application also maintains a peer-to-peer Video-stream (WebRTC with MixedReality Capture). This stream works well over the whole lifetime of the application flawlessly.
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
public class UdpCommunicationDotNet : ICommunicator
{
#region Fields
private int m_PackageCountPerSecond;
private int m_PackageCountTotal;
private Thread m_PackageCounterResetRoutine;
private Socket m_SenderSocket;
private Socket m_ReceiverSocket;
private IPEndPoint m_ServerIpEndPoint;
private IPEndPoint m_ReceiverIpEndPoint;
private IPEndPoint m_ListenerIpEndPoint;
private EndPoint m_ServerEndPoint;
private EndPoint m_ReceiverEndPoint;
private byte[] m_ReceiveBuffer;
private IDataProvider m_DataProvider;
private int m_MaxBufferByteLength;
private bool m_ReceiveEnabled = true;
public IDataProvider DataProvider { get => m_DataProvider; set => m_DataProvider = value; }
#endregion
#region Constructor
public UdpCommunicationDotNet()
{
m_MaxBufferByteLength = GameManager.Instance.GetConfigurationManager.RuntimeConfig.NetworkSettings.MaxBufferByteLength;
}
#endregion
#region Public Methods
public void Initialize(DataLineConfig dataLineConfig)
{
m_ReceiveBuffer = new byte[m_MaxBufferByteLength];
m_ServerIpEndPoint = dataLineConfig.serverEndPoint;
m_ReceiverIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
m_ServerEndPoint = (EndPoint)m_ServerIpEndPoint;
m_ReceiverEndPoint = (EndPoint)m_ReceiverIpEndPoint;
m_ListenerIpEndPoint = dataLineConfig.receiverEndPoint;
}
public void StartReceiver()
{
if (InitializeReceiverSocket())
{
m_ReceiveEnabled = true;
StartReceiving();
}
}
public void EndReceiver()
{
m_ReceiveEnabled = false;
}
public void StartSender()
{
InitializeSenderSocket();
}
public void Send(Byte[] data)
{
try
{
//added this, remove it
//Debug.Log("SentMyDataPackage");
m_SenderSocket.BeginSendTo(data, 0, data.Length, SocketFlags.None, m_ServerEndPoint, new AsyncCallback(OnSendCallback), null);
}
catch (Exception e)
{
Debug.LogError("Failed to send udp data through the UdpCommunicator: " + e.Message);
}
}
#endregion
#region Private Methods
private bool InitializeReceiverSocket()
{
bool isInitialized = false;
try
{
m_ReceiverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_ReceiverSocket.Bind(m_ListenerIpEndPoint);
isInitialized = true;
}
catch (Exception e)
{
Debug.LogError("Failed to initialize the receiver socket in the UdpCommunicator: " + e.Message);
}
return isInitialized;
}
private void InitializeSenderSocket()
{
m_SenderSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
}
private void StartReceiving()
{
m_ReceiverSocket.BeginReceiveFrom(m_ReceiveBuffer, 0, m_ReceiveBuffer.Length, SocketFlags.None, ref m_ReceiverEndPoint, new AsyncCallback(OnReceiveCallback), m_ReceiverEndPoint);
}
private void DistributeData(object dataObject)
{
byte[] data = (byte[])dataObject;
m_DataProvider.DistributeData(data);
}
#endregion
#region Callback Methods
private void OnSendCallback(IAsyncResult asyncResult)
{
try
{
m_SenderSocket.EndSend(asyncResult);
}
catch (Exception e)
{
Debug.LogError("Failed to close the opened send connection in the UdpCommunicator: " + e.Message);
}
}
private void OnReceiveCallback(IAsyncResult asyncResult)
{
try
{
if (DebugManager.Instance.isActive)
{
DebugManager.Instance.m_PackageCounter.UpdateMainCountTotal(m_PackageCountTotal);
}
int receivedBufferSize = m_ReceiverSocket.EndReceiveFrom(asyncResult, ref m_ReceiverEndPoint);
Array.Resize(ref m_ReceiveBuffer, receivedBufferSize);
byte[] copiedBuffer = new byte[receivedBufferSize];
Buffer.BlockCopy(m_ReceiveBuffer, 0, copiedBuffer, 0, receivedBufferSize);
Thread thread = new Thread(DistributeData);
thread.SetApartmentState(ApartmentState.STA);
thread.Start(copiedBuffer);
m_ReceiveBuffer = new byte[m_MaxBufferByteLength];
}
catch (Exception e)
{
Debug.LogError("Failed to fetch the received data in the UdpCommunicator: " + e.Message);
}
finally
{
if (m_ReceiveEnabled)
{
StartReceiving();
}
else
{
m_ReceiverSocket.Shutdown(SocketShutdown.Both);
m_SenderSocket.Shutdown(SocketShutdown.Both);
m_ReceiverSocket.Close();
m_SenderSocket.Close();
}
}
}
#endregion
}
Edit:
By writing the Minimal Reproducable Example I found out the reason for the missbehaviour! I realized that if I send more than 4 Packages in one chunk (so send package1, send package2, send package3, send package4, etc, wait x ms, start again) HoloLens2 is starting to drop my udp packages.
In contrast, when I send Package1-> wait for 4 ms -> send package2 -> wait for 4 ms -> send package 3 -> wait 4ms and so on and after sending all different packages simply restart sending, it Works like a charm!
Also, when I send the packages via EthernetOverUSB (what is not a usable approach for my case), even if I send all packages in one chunk it works.
For me this behaviour is wiered and I can´t explain it to myself. Maybe somebody of you can ? Anyways, thanks for anybody who tried to help me!
Related
I've written a tcp socket prgram that working with sockets asyncoronously.
This is some part of my code:
public void main()
{
var e = new SocketAsyncEventArgs();
e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
Task.Factory.StartNew(() =>
{
allDone.Reset();
mySocket.AcceptAsync(e);
allDone.WaitOne();
});
}
public void e_Completed(object sender, SocketAsyncEventArgs e)
{
var socket = (Socket)sender;
ThreadPool.QueueUserWorkItem(HandleTcpRequest, e.AcceptSocket);
e.AcceptSocket = null;
socket.AcceptAsync(e);
}
public void HandleTcpRequest(object state)
{
var mySocket = (Socket)state;
try
{
//do some codes and work with mySocket
}
catch (Exception ex)
{
}
finally
{
mySocket.Close();
mySocket.Dispose();
}
}
I've seen lots of \device\afd in process explorer in my process. I've read and searched a lot about this and found that it is related to the Ancillary Function Driver and the Transport Driver Interface. How can I resolve this handle leak?
==========> edited my code:
Edited to accept only 10 sockets in sync way.
Feel that program is more faster, but when push my finger on Ctrl+F5, find that
there are more than 10 \device\afd in process explorer and when continuing too push, see more \device\afd, but lower that above code.
mySocket.Listen(10);
while (true)
{
using (Socket so = mySocket.Accept())
{
HandleTcpRequest(so);
}
}
I have an issue about the server-client communication.
I googled around but I did not find a solution to this.
Right now I am using 32feet in order to get in touch 2 or more (till 7) BT clients to 1 BT server.
I need to broadcast a message from the server to every device in the same time, but I don't know how to do it.
The only way I figured out was to use the list of connection in order to send the message one per time, but it means a delay between each message sent (around 100 ms per device). Unfortunately it means to have a large delay on the last one.
Can someone please give me an advice on how to solve this problem?
Is there a way to broadcast the message to all devices in the same time?
If it can be helpfull, here there is the handle of connection and reading from devices.
Thanks for your help
private void btnStartServer_Click(object sender, EventArgs e)
{
btnStartClient.Enabled = false;
ConnectAsServer();
}
private void ConnectAsServer()
{
connessioniServer = new List<BluetoothClient>();
// thread handshake
Thread bluetoothConnectionControlThread = new Thread(new ThreadStart(ServerControlThread));
bluetoothConnectionControlThread.IsBackground = true;
bluetoothConnectionControlThread.Start();
// thread connessione
Thread bluetoothServerThread = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerThread.IsBackground = true;
bluetoothServerThread.Start();
}
private void ServerControlThread()
{
while (true)
{
foreach (BluetoothClient cc in connessioniServer)
{
if (!cc.Connected)
{
connessioniServer.Remove(cc);
break;
}
}
updateConnList();
Thread.Sleep(0);
}
}
Guid mUUID = new Guid("fc5ffc49-00e3-4c8b-9cf1-6b72aad1001a");
private void ServerConnectThread()
{
updateUI("server started");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
while (true)
{
BluetoothClient conn = blueListener.AcceptBluetoothClient();
connessioniServer.Add(conn);
Thread appoggio = new Thread(new ParameterizedThreadStart(ThreadAscoltoClient));
appoggio.IsBackground = true;
appoggio.Start(conn);
updateUI(conn.RemoteMachineName+" has connected");
}
}
private void ThreadAscoltoClient(object obj)
{
BluetoothClient clientServer = (BluetoothClient)obj;
Stream streamServer = clientServer.GetStream();
streamServer.ReadTimeout=1000;
while (clientServer.Connected)
{
try
{
int bytesDaLeggere = clientServer.Available;
if (bytesDaLeggere > 0)
{
byte[] bytesLetti = new byte[bytesDaLeggere];
int byteLetti = 0;
while (bytesDaLeggere > 0)
{
int bytesDavveroLetti = streamServer.Read(bytesLetti, byteLetti, bytesDaLeggere);
bytesDaLeggere -= bytesDavveroLetti;
byteLetti += bytesDavveroLetti;
}
updateUI("message sent from "+clientServer.RemoteMachineName+": " + System.Text.Encoding.Default.GetString(bytesLetti));
}
}
catch { }
Thread.Sleep(0);
}
updateUI(clientServer.RemoteMachineName + " has gone");
}
private void updateUI(string message)
{
Func<int> del = delegate()
{
textBox1.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateConnList()
{
Func<int> del = delegate()
{
listaSensori.Items.Clear();
foreach (BluetoothClient d in connessioniServer)
{
listaSensori.Items.Add(d.RemoteMachineName);
}
return 0;
};
try
{
Invoke(del);
}
catch { }
}
I don't exactly understand how you do it right now (the italian names are not helping...) but maybe my solution can help you.
first of all, bluetooth classic does not support broadcast. so you have to deliver at one at a time.
i do connect to 7 serial port devices at a time, using 7 threads. then i tell every thread to send data. this is very close to same time, but of course not exactly.
let me know if that helps or if you need a code example.
this is my first post, sorry in advance if I do something I shouldn't. I always search here for answer but this time I saw nothing about my problem. I have a project in C# where I keep alive a connection UDP listening a multicast IP from a data streaming.
The IP I'm listening is a multicast streamer that sends tracking data from many tracking systems, so we can assume the sender is not the problem. It sends like 1024 bytes packets, 60 fps.
This is a small example extracted from the whole project, simplified and as far as I tested, behaves in the same way as in the big project. The problem is that if I connect in localhost this never break, but if I connect to remote IPs this stop working, more or less, in 4 minutes.
public class TrackingStateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = 65507;
public byte[] buffer = new byte[BUFFER_SIZE];
}
class MainClass
{
static public string multicastServerIPAddress = "239.255.42.99";
static public string realTrackingServerIPAddress = "161.116.27.144";
static protected EndPoint trackingEndPoint;
static public int dataPort = 2345;
static protected Socket sockData = null;
static int foo = 0;
public static void Main (string[] args)
{
IPEndPoint ipep;
TrackingStateObject so;
IPAddress trackingIP = IPAddress.Parse(multicastServerIPAddress);
trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
sockData = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
ipep = new IPEndPoint(IPAddress.Any, dataPort);
try {
sockData.Bind(ipep);
}
catch (Exception ex) {
System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
return;
}
sockData.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(trackingIP));
try {
trackingIP = IPAddress.Parse(realTrackingServerIPAddress);
trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
}
catch(Exception ex) {
System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
return;
}
so = new TrackingStateObject();
so.workSocket = sockData;
sockData.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, 0, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);
System.Threading.Thread.Sleep (600000);
}
private static void AsyncReceiveCallback(IAsyncResult ar)
{
try {
TrackingStateObject so = (TrackingStateObject)ar.AsyncState;
Socket sock = so.workSocket;
int read = sock.EndReceiveFrom(ar, ref trackingEndPoint);
if (read > 0)
{
// Do things with the data
System.Console.WriteLine("Recieved shit, " + read + " bytes, " + foo++ + " times.");
}
sock.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, SocketFlags.None, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);
}
catch (Exception e) {
System.Console.WriteLine("[UDPClient] Exception AsynCallback "+e.Message);
}
}
}
I debugged for a while and as far I can see is that always sock.BeginReceiveFrom is called, stop in some point, AsyncReceiveCallback is never executed again. Perhaps I'm doing here something stupid, but in any case, I'm not able to see it. Thanks!
I was having exactly the same problem, which only seems to occur on WiFi interfaces, not hardwired interfaces. The solution I discovered was to always set the SocketOptionName.AddMembership option before calling BeginReceiveFrom().
In the receive callback, after calling EndReceiveFrom() then set the SocketOptionName.DropMembership option for the multicast address.
Then before calling BeginReceiveFrom() again, set the SocketOptionName.AddMembership option.
Not sure why this has to be done for WiFi interfaces, but it worked for me.
I need to send string messages from Java program to C# program in real time.
There are many examples in the Internet but U can't find anything good for my purpose that is (probably) Java client (sockets code) and c# server (sockets code).
Thank you.
Ok i already did this in one of my projects so here it is:
disclaimer: some of the code (only a little bit actually) is based on nakov chat server.
also note that i decode and encode all the messages sent and recived in UTF-8.
Java Code:
Class: Server
import java.net.*;
import java.io.*;
import javax.swing.*;
public class Server
{
private static void createAndShowGUI() {
//Create and set up the window
}
public static final int LISTENING_PORT = 2002;
public static void main(String[] args)
{
// Open server socket for listening
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(LISTENING_PORT);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
//System.out.println("Server started on port " + LISTENING_PORT);
}
catch (IOException se)
{
System.err.println("Can not start listening on port " + LISTENING_PORT);
se.printStackTrace();
System.exit(-1);
}
// Start ServerDispatcher thread
ServerDispatcher serverDispatcher = new ServerDispatcher();
// Accept and handle client connections
while (true)
{
try
{
Socket socket = serverSocket.accept();
ClientInfo clientInfo = new ClientInfo();
clientInfo.mSocket = socket;
ClientListener clientListener =
new ClientListener(clientInfo, serverDispatcher);
ClientSender clientSender =
new ClientSender(clientInfo, serverDispatcher);
clientInfo.mClientListener = clientListener;
clientInfo.mClientSender = clientSender;
clientListener.start();
clientSender.start();
serverDispatcher.addClient(clientInfo);
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
Class Message Dispatcher:
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.*;
public class ServerDispatcher
{
private Vector mMessageQueue = new Vector();
private Vector<ClientInfo> mClients = new Vector<ClientInfo>();
public synchronized void addClient(ClientInfo aClientInfo) {
mClients.add(aClientInfo);
}
public synchronized void deleteClient(ClientInfo aClientInfo) {
int clientIndex = mClients.indexOf(aClientInfo);
if (clientIndex != -1)
mClients.removeElementAt(clientIndex);
}
private synchronized void sendMessageToAllClients(String aMessage)
{
for (int i = 0; i < mClients.size(); i++) {
ClientInfo infy = (ClientInfo) mClients.get(i);
infy.mClientSender.sendMessage(aMessage);
}
}
public void sendMessage(ClientInfo aClientInfo, String aMessage) {
aClientInfo.mClientSender.sendMessage(aMessage);
}
}
Class: ClientInfo
/**
*
* ClientInfo class contains information about a client, connected to the server.
*/
import java.awt.List;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Vector;
public class ClientInfo
{
public int userID=-1;
public Socket mSocket = null;
public ClientListener mClientListener = null;
public ClientSender mClientSender = null;
}
Class ClientListner:
/**
* ClientListener class is purposed to listen for client messages and
* to forward them to ServerDispatcher.
*/
import java.io.*;
import java.net.*;
public class ClientListener extends Thread {
private ServerDispatcher mServerDispatcher;
private ClientInfo mClientInfo;
private BufferedReader mIn;
private String message;
private String decoded = null;
public ClientListener(ClientInfo aClientInfo,
ServerDispatcher aServerDispatcher) throws IOException {
mClientInfo = aClientInfo;
mServerDispatcher = aServerDispatcher;
Socket socket = aClientInfo.mSocket;
mIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
/**
* Until interrupted, reads messages from the client socket, forwards them
* to the server dispatcher and notifies the server dispatcher.
*/
public void run() {
message = "";
while (!isInterrupted()) {
try {
message = mIn.readLine();
if (message == null)
break;
try {
decoded = URLDecoder.decode(message, "UTF-8");
} catch (UnsupportedEncodingException e)
e.printStackTrace();
}
mServerDispatcher.sendMessage(mClientInfo, decoded);
}
catch (IOException e) {
break;
}
}
// Communication is broken. Interrupt both listener and sender threads
mClientInfo.mClientSender.interrupt();
mServerDispatcher.deleteClient(mClientInfo);
}
}
Class:ClientSender
/**
* Sends messages to the client. Messages are stored in a message queue. When
* the queue is empty, ClientSender falls in sleep until a new message is
* arrived in the queue. When the queue is not empty, ClientSender sends the
* messages from the queue to the client socket.
*/
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientSender extends Thread
{
private Vector mMessageQueue = new Vector();
private ServerDispatcher mServerDispatcher;
private ClientInfo mClientInfo;
private PrintWriter mOut;
public ClientSender(ClientInfo aClientInfo, ServerDispatcher aServerDispatcher)
throws IOException
{
mClientInfo = aClientInfo;
mServerDispatcher = aServerDispatcher;
Socket socket = aClientInfo.mSocket;
mOut = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
/**
* Adds given message to the message queue and notifies this thread
* (actually getNextMessageFromQueue method) that a message is arrived.
* sendMessage is called by other threads (ServeDispatcher).
*/
public synchronized void sendMessage(String aMessage)
{
mMessageQueue.add(aMessage);
notify();
}
/**
* #return and deletes the next message from the message queue. If the queue
* is empty, falls in sleep until notified for message arrival by sendMessage
* method.
*/
private synchronized String getNextMessageFromQueue() throws InterruptedException
{
while (mMessageQueue.size()==0)
wait();
String message = (String) mMessageQueue.get(0);
mMessageQueue.removeElementAt(0);
return message;
}
/**
* Sends given message to the client's socket.
*/
private void sendMessageToClient(String aMessage)
{
String encoded;
try {
encoded = URLEncoder.encode(aMessage,"UTF-8");
mOut.println(encoded);
mOut.flush();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Until interrupted, reads messages from the message queue
* and sends them to the client's socket.
*/
public void run()
{
try {
while (!isInterrupted()) {
String message = getNextMessageFromQueue();
sendMessageToClient(message);
}
} catch (Exception e) {
// Commuication problem
break;
}
// Communication is broken. Interrupt both listener and sender threads
mClientInfo.mClientListener.interrupt();
mServerDispatcher.deleteClient(mClientInfo);
}
}
Ok this is the java code,now to the c# code
c# Code:
Varibales used:
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
Function: Intelize connection:
private void InitializeConnection()
{
// Parse the IP address
string ipAdress = "XXX.XXX.XXX.XXX";
ipAddr = IPAddress.Parse(ipAdress);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
try
{
tcpServer.Connect(ipAddr, 2002);
swSender = new StreamWriter(tcpServer.GetStream());
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
Connected=true;
}
catch (Exception e2)
{
MessageBox.Show(e2.ToString());
}
}
}
Function: ReciveMessages
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
while (Connected)
{
String con = srReceiver.ReadLine();
string StringMessage = HttpUtility.UrlDecode(con, System.Text.Encoding.UTF8);
processMessage(StringMessage);
}
}
Function: proceesMessage:
private void processMessage(String p)
{
// do something with the message
}
Function sendMessage:
private void SendMessage(String p)
{
if (p != "")
{
p = HttpUtility.UrlEncode(p, System.Text.Encoding.UTF8);
swSender.WriteLine(p);
swSender.Flush();
}
}
thats it thats all you need to have communication between java server and c# client. if you have any questions dont hesitate to post them here.
Choose a protocol for encoding/sending your strings. For instance:
<length of string (4 bytes)><string data (length bytes)>
Write some Java code to send a string that follows whatever protocol you chose in #1. So using the example above, you could do something like:
public static void writeString(String string, OutputStream out) throws IOEXception {
if (string == null || "".equals(string)) {
//nothing to do
return;
}
int length = string.length();
//synchronize so that two threads don't try to write to the same stream at the same time
synchronized(out) {
out.write((length >> 24) & 0xFF);
out.write((length >> 16) & 0xFF);
out.write((length >> 8) & 0xFF);
out.write(length & 0xFF);
out.write(string.getBytes());
out.flush();
}
}
Write some equivalent code in C# to decode the strings that are being sent. It will look a lot like your Java code, except with reads instead of writes.
I think I've found a good, working solution. Using UDP sockets:
Java code
public void runJavaSocket() {
System.out.println("Java Sockets Program has started."); int i=0;
try {
DatagramSocket socket = new DatagramSocket();
System.out.println("Sending the udp socket...");
// Send the Message "HI"
socket.send(toDatagram("HI",InetAddress.getByName("127.0.0.1"),3800));
while (true) {
System.out.println("Sending hi " + i);
Thread.currentThread();
Thread.sleep(1000);
socket.send(toDatagram("HI " +
String.valueOf(i),InetAddress.getByName("127.0.0.1"),3800));
i++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public DatagramPacket toDatagram(
String s, InetAddress destIA, int destPort) {
// Deprecated in Java 1.1, but it works:
byte[] buf = new byte[s.length() + 1];
s.getBytes(0, s.length(), buf, 0);
// The correct Java 1.1 approach, but it's
// Broken (it truncates the String):
// byte[] buf = s.getBytes();
return new DatagramPacket(buf, buf.length, destIA, destPort);
}
C# code
string returnData;
byte[] receiveBytes;
//ConsoleKeyInfo cki = new ConsoleKeyInfo();
using (UdpClient udpClient =
new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3800)))
{
IPEndPoint remoteIpEndPoint =
new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3800);
while (true)
{
receiveBytes = udpClient.Receive(ref remoteIpEndPoint);
returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
}
I would just use SOAP protocol. You can use WCF on the C# side and JMS (Java messging) on the Java side. Both these technologies are built on SOAP so they can read each other's messages. They both use WSDL.
How can I check if a UNC Path is available?
I have the problem that the check takes about half a minute if the share is not available :
var fi = new DirectoryInfo(#"\\hostname\samba-sharename\directory");
if (fi.Exists)
//...
Is there a faster way to check if a folder is available?
I'm using Windows XP and C#.
How's this for a quick and dirty way to check - run the windows net use command and parse the output for the line with the network path of interest (e.g. \\vault2) and OK. Here's an example of the output:
C:\>net use
New connections will be remembered.
Status Local Remote Network
-------------------------------------------------------------------------------
OK O: \\smarty\Data Microsoft Windows Network
Disconnected P: \\dummy\Data Microsoft Windows Network
OK \\vault2\vault2 Microsoft Windows Network
The command completed successfully.
It's not a very .netish solution, but it's very fast, and sometimes that matters more :-).
And here's the code to do it (and LINQPad tells me that it only takes 150ms, so that's nice)
void Main()
{
bool available = QuickBestGuessAboutAccessibilityOfNetworkPath(#"\\vault2\vault2\dir1\dir2");
Console.WriteLine(available);
}
public static bool QuickBestGuessAboutAccessibilityOfNetworkPath(string path)
{
if (string.IsNullOrEmpty(path)) return false;
string pathRoot = Path.GetPathRoot(path);
if (string.IsNullOrEmpty(pathRoot)) return false;
ProcessStartInfo pinfo = new ProcessStartInfo("net", "use");
pinfo.CreateNoWindow = true;
pinfo.RedirectStandardOutput = true;
pinfo.UseShellExecute = false;
string output;
using (Process p = Process.Start(pinfo)) {
output = p.StandardOutput.ReadToEnd();
}
foreach (string line in output.Split('\n'))
{
if (line.Contains(pathRoot) && line.Contains("OK"))
{
return true; // shareIsProbablyConnected
}
}
return false;
}
Or you could probably go the route of using WMI, as alluded to in this answer to How to ensure network drives are connected for an application?
In my project I use the System.IO :
if (Directory.Exists(#"\\hostname\samba-sharename\directory")) { ...
and it's pretty fast so far...
In a project of mine, i had to check whether a server connection was established or not. I used a TCP Socket to asynchronically check whether the server could be reached or not. I wonder if you could use this to check on a network share. The async TCP Socket connect goes so fast i tested for the connection 10 times under 60 miliseconds. Maybe you could play around with that a bit ?
EDIT: Here is the Asynchronous Socket i used for my project. Use this class to check for a certain IP or address. Hope it is of any use to you
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Base.BaseObjects
{
public class AsynchronousClient
{
#region Properties
private int _port = 0000, currentTry = 0, _buffersize, _fastpingdelay = 80;
private string _server = "localhost";
private Socket client;
private static IPEndPoint remoteEP;
// Delegates & Events
public delegate void SendMessageDelegate(string message);
public event SendMessageDelegate SendMessageEvent;
public delegate void ConnectionStatusDelegate(bool connected, bool reconnect);
public event ConnectionStatusDelegate ConnectionStatusChanged;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
/// <summary>
/// Port to monitor
/// </summary>
public int Port { get { return _port; } }
/// <summary>
/// Number of packages to buffer until system reports connection loss
/// </summary>
public int BufferSize { get { return _buffersize; } }
/// <summary>
/// Time in milliseconds between two pings
/// </summary>
public int FastPingDelay { get { return _fastpingdelay; } }
/// <summary>
/// Servername to connect to
/// </summary>
public string Server
{
get { return _server; }
set
{
_server = value;
// Resolve the remote endpoint for the socket.
try
{
IPAddress ipAddress = (IPAddress)Dns.GetHostAddresses(value)[0];
remoteEP = new IPEndPoint(ipAddress, Port);
}
catch (SocketException ex)
{
SendMessage(ex.Message);
}
}
}
#endregion
#region Events & Delegates
protected void SendMessage(string message)
{
if (SendMessageEvent != null)
SendMessageEvent(message);
}
protected void UpdateConnectionStatus(bool connected, bool reconnect)
{
if (ConnectionStatusChanged != null)
ConnectionStatusChanged(connected, reconnect);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
SendMessage(String.Format("Socket connected to {0}", client.RemoteEndPoint.ToString()));
//UpdateConnectionStatus(true, false);
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
SendMessage(e.ToString());
UpdateConnectionStatus(false, true);
}
}
#endregion
#region methods
public AsynchronousClient(int port, string server)
{
_port = port;
Server = server;
_buffersize = 10;
_fastpingdelay = 20;
}
public void CreateSocket()
{
try
{
StopClient();
}
catch (Exception ex)
{
SendMessage(ex.Message);
}
finally
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
}
public bool FastPingSocket()
{
for (currentTry = 0; currentTry <= BufferSize; currentTry++)
{
try
{
CreateSocket();
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
System.Threading.Thread.Sleep(FastPingDelay);
client.Shutdown(SocketShutdown.Receive);
connectDone.WaitOne();
client.Close();
return true;
}
catch (SocketException ex)
{
SendMessage(ex.Message);
}
catch (ObjectDisposedException ex)
{
currentTry--;
SendMessage(ex.Message);
CreateSocket();
}
catch (NullReferenceException ex)
{
currentTry--;
SendMessage(ex.Message);
CreateSocket();
}
catch (ArgumentNullException ex)
{
SendMessage(ex.Message);
CreateSocket();
}
catch (InvalidOperationException ex)
{
SendMessage(ex.Message);
CreateSocket();
currentTry--;
}
finally
{
StopClient();
}
}
UpdateConnectionStatus(false, true);
return false;
}
public void StopClient()
{
// Release the socket.
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception) { }
finally
{
UpdateConnectionStatus(false, false);
}
}
#endregion
}
}
Edit: Please don't just copy/paste it. Try to understand the code so you can use it for your benefit, and finetune it for your needs.
I ended up "cheating" and just pinging the host, which is reasonable as that in reality is the case that I'm checking for.
private bool HostExists(string PCName)
{
Ping pinger = new Ping();
try
{
PingReply reply = pinger.Send(PCName);
return reply.Status == IPStatus.Success;
}
catch
{
return false;
}
finally
{
pinger.Dispose();
}
}
This way suits me best because of its speed, simplicity, and reliability.
I used the ping method suggested above and it did not work for me since I am using OpenDNS
Here is a function that worked well for me:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// <summary>
/// A quick method to test is the path exists
/// </summary>
/// <param name="s"></param>
/// <param name="timeOutMs"></param>
/// <returns></returns>
public static bool CheckPathExists(string s, int timeOutMs = 120) {
if (s.StartsWith(#"\\")) {
Uri uri = new Uri(s);
if (uri.Segments.Length == 0 || string.IsNullOrWhiteSpace(uri.Host))
return false;
if (uri.Host != Dns.GetHostName()) {
WebRequest request;
WebResponse response;
request = WebRequest.Create(uri);
request.Method = "HEAD";
request.Timeout = timeOutMs;
try {
response = request.GetResponse();
} catch (Exception ex) {
return false;
}
return response.ContentLength > 0;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Do a Ping to see if the server is there
// This method doesn't work well using OPenDNS since it always succeeds
// regardless if the IP is a valid or not
// OpenDns always maps every host to an IP. If the host is not valid the
// OpenDNS will map it to 67.215.65.132
/* Example:
C:\>ping xxx
Pinging xxx.RT-AC66R [67.215.65.132] with 32 bytes of data:
Reply from 67.215.65.132: bytes=32 time=24ms TTL=55
*/
//Ping pingSender = new Ping();
//PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
//options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
//string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//byte[] buffer = Encoding.ASCII.GetBytes(data);
//int timeout = 120;
//PingReply reply = pingSender.Send(uri.Host, timeout, buffer, options);
//if (reply == null || reply.Status != IPStatus.Success)
// return false;
}
}
return File.Exists(s);
}
Thats probably the quickest way, the delay will be the general network speed/disk access etc.
If this is causing a delay for the user, you could try checking this asynchronously?
Maybe you should try to create the folder, if it does exist, it will return an error that you could catch. There should be no default timeout.