We use SharpSVN to programmatically access SVN repositories. Now we have the problem that the access to local repositories via svn:// or http:// urls is very slow - every access needs at least one second, and our app needs to fetch a bunch of properties and directory listings.
We could reproduce the problem on two different machines, both are Windows 7 32 bit and are in the same domain. The SVN servers are VisualSVN 2.1.9 for http:// urls and the CollabNet 1.6.17 for svn:// urls. It appears for connections via "localhost" and via the host name. It appears in our C# application, as well as a small testbed app using IronPython and when calling the SharpSvn svn.exe command.
This problem does not happen when accessing when accessing remote repositories (Both a linux and a windows XP server) - here, each access is between 0.01 and 0.08 secs, which is expected due to network latency. The Problem also does not happen when acessing the local repositories via file:// urls or when accessing the repositories via "native" svn command line tools from CollabNet.
Now my question is: Has Windows 7 or .NET or SharpSVN some built-in limit which only applies to localhost connections?
(Addition: I now found out that this limit also applies when connecting via a small C# test program using System.Net.Sockets.TcpClient:
Server:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace TcpSpeedServer
{
class Program
{
public static void Main()
{
Int32 port = 47011;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
var server = new TcpListener(localAddr, port);
server.Start();
Console.WriteLine("Listening on {0} : {1}", localAddr, port);
ulong count = 0;
// Enter the listening loop.
while(true)
{
using (var client = server.AcceptTcpClient()) {
Console.WriteLine("Connected: {0} {1}!", count, client.Client.RemoteEndPoint);
count += 1;
using (var stream = client.GetStream()) {
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
{
string query = reader.ReadLine();
writer.WriteLine("GET / HTTP/1.0");
writer.WriteLine();
writer.Flush();
}
}
}
}
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
namespace TcpSpeedTest
{
class Program
{
const bool ASYNC = false;
static DateTime s_now;
public static void Main(string[] args)
{
var liste = new List<object>();
s_now = DateTime.Now;
for (int i=0; i < 100; i += 1) {
if (ASYNC)
ThreadPool.QueueUserWorkItem(connect, i);
else
connect(i);
}
Console.WriteLine("outer: " + (DateTime.Now - s_now));
Console.ReadLine();
}
private static void connect(object i)
{
DateTime now = DateTime.Now;
using (TcpClient client = new TcpClient("localhost", 47011))
{
var stream = client.GetStream();
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
{
writer.WriteLine("GET / HTTP/1.0");
writer.WriteLine();
writer.Flush();
string result = reader.ReadLine();
}
}
Console.WriteLine(string.Format("inner: {0} - {1} - {2}", i, DateTime.Now - now, DateTime.Now - s_now));
}
}
}
So this problem seems not to be subversion specific.)
Addition2: When running the client under Mono 2.10 for windows, the problem does not appear. So it seems to be specific to .NET framework.
Addition3: It seems to be an IPv6 related problem. The server only listens on IPv4, but the hostname also resolves to IPv6. Now it seems that the OS code internally tries the IPv6 connection, and after getting the connection reset, waits 1 sec before falling back to IPv4. And this game is repeated for every single connection attempt. http://msdn.microsoft.com/en-us/library/115ytk56.aspx documents that for TcpClient (thanks to Andreas Johansson from the MSDN forums for the hint!), and it seems that the APR used by Apache internally uses a similar mechanism.
Addition 3 is also the solution to your problem. To fix this, either make DNS/hosts file only resolve to an IPv4 address, or make the IPv6 server(s) work.
You can enter in C:\Windows\System32\drivers\etc\hosts something like:
127.0.0.1 localhost-ipv4
And then use that name to connect.
You can also make svnserve listen to IPv6 addresses. A quick search for svnserve options [revealed][1] that it defaults to IPv6, so in its startup parameters is probably a --listen-host. Try removing that, or when it's not present forcing it to run at IPv6.
The same can be done for the Apache webserver:
Listen 0.0.0.0:80
Listen [::]:80
Related
I have searched everywhere but couldn't find as they are all answering to send message to all clients. What I want to achieve is multiple clients request to server to request data from another client and other client sends data to server telling it that data is for requesting client and so. I don't know how to achieve this. I'm new to this.
What I want to achieve:
I have tried with Data sending client to listen and requesting client to connect to it and transfer data. I have achieved this on local network but to make it work online it needs port forwarding and my user will be a lot of different people so port forwarding is not possible for every user. So I can rent a server which will act as a center of transfer. I programmed a test server in console which will listen to a server IP:port X and accept new clients and their data on port X and forward it to server IP:port Y but what this does is send data to all clients on port Y. I cannot send it to clients public ip address directly for obvious reasons. I understand that all the requesting clients are connected to port Y but I cannot create and assign new ports to all the clients interacting. So I want a way to determine how to request and receive the data without the need of assigning or creating new ports to different clients on same server.
What I have tried:
Server code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Test___server
{
class server
{
public static string serverIP = "192.168.0.102";
static void Main(string[] args)
{
Thread listenSendingThread = new Thread(listenSending);
listenSendingThread.IsBackground = true;
listenSendingThread.Start();
Thread listenReceivingThread = new Thread(listenReceiving);
listenReceivingThread.IsBackground = true;
listenReceivingThread.Start();
Console.ReadKey();
}
public static List<TcpClient> listSending = new List<TcpClient>();
public static List<TcpClient> listReceiving = new List<TcpClient>();
public static TcpClient clientSending = null;
private static void listenSending()
{
TcpListener listenerSending = new TcpListener(IPAddress.Parse(serverIP), 5319);
listenerSending.Start();
Console.WriteLine("Server listening to " + serverIP + ":5319");
while(true)
{
clientSending = listenerSending.AcceptTcpClient();
listSending.Add(clientSending);
Console.WriteLine("Sender connection received from " + clientSending.Client.RemoteEndPoint);
}
}
private static void send()
{
StreamWriter sw = new StreamWriter(clientSending.GetStream());
sw.WriteLine(message);
sw.Flush();
Console.WriteLine("Message sent!");
}
public static string message = string.Empty;
private static void listenReceiving()
{
TcpListener listener = new TcpListener(IPAddress.Parse(serverIP), 0045);
listener.Start();
Console.WriteLine("Server listening to " + serverIP + ":0045");
while (true)
{
TcpClient client = listener.AcceptTcpClient();
listReceiving.Add(client);
Console.WriteLine("Receiver connection received from " + client.Client.RemoteEndPoint);
StreamReader sr = new StreamReader(client.GetStream());
message = sr.ReadLine();
send();
}
}
}
}
Requesting client code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test____admin
{
class admin
{
static void Main(string[] args)
{
Console.WriteLine("Begin");
string serverIP = "192.168.0.102";
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect(serverIP, );
Console.WriteLine("Connected");
while (true)
{
Console.WriteLine("Reading");
StreamReader sr = new StreamReader(clientSocket.GetStream());
Console.WriteLine("Message: " + sr.ReadLine());
}
}
}
}
Request satisfying client code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Test___client
{
class client
{
public static string serverIP = "192.168.0.102";
static void Main(string[] args)
{
clientConnect();
}
private static void clientConnect()
{
try
{
TcpClient client = new TcpClient(serverIP, 0045);
StreamWriter sw = new StreamWriter(client.GetStream());
sw.WriteLine("Karan!");
sw.Flush();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
You are using a very low-level API, and doing it the right way is challenging. Instead, try YARP as a reverse proxy. The requesting client should notify the reverse proxy about the desired destination client. One option is sending the destination client name in the request header. You will also need to split a single server request into multiple client requests, then merge their responses into a single one. You can achieve it by implementing Transphorms.
I'm not sure this approach applies to your situation because clients should implement server API using REST, Grpc or any other supported technology.
I'm trying to pass messages with NetMQ in C# UWP to python.
The python acts as Subscriber, and the C# as Publisher.
When I use C# .Net Core, I can see messages get to the python subscriber, but when I use C# UWP, nothing happens, though the code is exactly the same and I can see Publisher is sending the messages.
The code in python: (Working)
import zmq
import time
def subscribe():
port = "6789"
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:%s" % port)
topicfilter = "abcde"
socket.setsockopt(zmq.SUBSCRIBE, topicfilter)
while True:
string = socket.recv()
print string
subscribe()
The code in .Net Core: (Working)
using System.Threading;
using System.Threading.Tasks;
using NetMQ;
using NetMQ.Sockets;
namespace Examples
{
static partial class Program
{
public static void Main(string[] args)
{
Publisher();
}
public static void Publisher()
{
Task.Run(async () =>
{
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:6789");
for (var i = 0; i < 10; i++)
{
pubSocket.SendFrame("abcde" + i.ToString());
Thread.Sleep(1000);
}
}
});
}
}
}
But the code in UWP (Not working):
using NetMQ;
using NetMQ.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System;
namespace test_NetMQ_UWP
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
DataContext = this;
}
// this event happen when I click on a button in MainPage.xaml
private void Publisher_Click(object sender, RoutedEventArgs e)
{
Task.Run(async () =>
{
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:6789");
for (var i = 0; i < 10; i++)
{
pubSocket.SendFrame("abcde" + i.ToString());
Thread.Sleep(1000);
}
}
});
}
}
}
What am I doing wrong?
It's normal behavior. You're using an IP loopback address for Network communications between a UWP app and a different process (a different UWP app or a desktop app). This is restricted by network isolation.
You could run your server and client on different machine to test. Please see the document How to enable loopback and troubleshoot network isolation (Windows Runtime apps). It has explained this scenario:
Loopback is permitted only for development purposes. Usage by a Windows Runtime app installed outside of Visual Studio is not permitted. Further, a Windows Runtime app can use an IP loopback only as the target address for a client network request. So a Windows Runtime app that uses a DatagramSocket or StreamSocketListener to listen on an IP loopback address is prevented from receiving any incoming packets.
In your case, if you just want to test if the UWP app can send message to your python subscriber successfully. You could run the UWP app on another machine. I used your code to make a UWP app to send message and make a console application as subscriber which is run on a different machine. The console application can receive the message.
Please note that because your UWP app need to access the Network at runtime, you need to enable the Netwrok capabilities(Internet(Client) Internet(Client & Server) Private Networks(Client & Server)) in Package.appxmanifest file.
My pc is connected to the router of the network i want to scan but the not wireless the pc is connected with a cable to the router.
But my android device is connected to the network wireless.
So in logic in this case the results in the list should be my pc and my android device.
This is what i'm using now managed wifi api:
managed wifi api
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NativeWifi;
namespace ScanWifi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
WlanClient client = new WlanClient();
try
{
foreach (WlanClient.WlanInterface wlanIface in client.Interfaces)
{
Wlan.WlanBssEntry[] wlanBssEntries = wlanIface.GetNetworkBssList();
foreach (Wlan.WlanBssEntry network in wlanBssEntries)
{
int rss = network.rssi;
byte[] macAddr = network.dot11Bssid;
string tMac = "";
for (int i = 0; i < macAddr.Length; i++)
{
tMac += macAddr[i].ToString("x2").PadLeft(2, '0').ToUpper();
}
listView1.Items.Add("Found network with SSID {0}." + System.Text.ASCIIEncoding.ASCII.GetString(network.dot11Ssid.SSID).ToString());
listView1.Items.Add("Signal: {0}%."+ network.linkQuality);
listView1.Items.Add("BSS Type: {0}."+ network.dot11BssType);
listView1.Items.Add("MAC: {0}.", tMac);
listView1.Items.Add("RSSID:{0}", rss.ToString());
}
Console.ReadLine();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
When running the program i'm exception on WlanApi.cs on the line:
Wlan.ThrowIfError(
Wlan.WlanOpenHandle(Wlan.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out negotiatedVersion, out clientHandle));
System.ComponentModel.Win32Exception' occurred in ManagedWifi.dll
The service has not been started
For Windows 10, the service "WLAN AutoConfig" must be started for WlanClient to work. This service should be started automatically on a computer which has a WiFi adapter present. On a computer such as a desktop which does not have a WiFi adapter, the service startup type is probably Manual and not started; you can start it anyway and WlanClient should no longer throw any exceptions, but without a WiFi adapter, it won't see any interfaces, so you won't be able to get a list of networks.
According to the documentation of the [WlanOpenHandle ][1] function, the problem is that the Wireless Zero Configuration (WZC) service is not started on your machine:
WlanOpenHandle will return an error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive.
However, depending on your platform, it might also might be the case that you are simply passing the wrong parameters to the WlanOpenHandle function. Have you tried passing Wlan.WLAN_CLIENT_VERSION_LONGHORN as the first parameter?
i'm trying to make an application for my laptop which in case i forgot to log off, i can use my smarthphone to log off by using a specific app for that. So i was thinking usually if you have a router... you have a problem cause you don't have the external ip which you can use, and the port. For that i used this function to get the external ip.
public string adresaIP()
{
UTF8Encoding utf8 = new UTF8Encoding();
WebClient clientWeb = new WebClient();
String adresaIP = utf8.GetString(clientWeb.DownloadData("http://bot.whatismyipaddress.com"));
return adresaIP;
}
But when i try to use te IpEndPoint it dosen't work it give's me an exception Error and i don't know were i did wrong.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace bluetooth_LogOff
{
public partial class Form1 : Form
{
static byte[] buffer { get; set; }
static Socket soket;
public Form1()
{
InitializeComponent();
try
{
string ip = adresaIP();
soket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//soket.Bind(new IPEndPoint(IPAddress.Parse(ip),1234)); <<-- in this way dosen't work
soket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"),1234)); // <<- in this way it works....
soket.Listen(100);
Socket accept = soket.Accept();
buffer = new byte[accept.SendBufferSize];
int bytesRead = accept.Receive(buffer);
byte[] format = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
format[i] = buffer[i];
}
string primescMesaj = Encoding.ASCII.GetString(format);
MessageBox.Show(primescMesaj);
soket.Close();
accept.Close();
}
catch (Exception messaj)
{
MessageBox.Show(messaj.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = adresaIP();
}
public string adresaIP()
{
UTF8Encoding utf8 = new UTF8Encoding();
WebClient clientWeb = new WebClient();
String adresaIP = `utf8.GetString(clientWeb.DownloadData("http://bot.whatismyipaddress.com"));`
return adresaIP;
}
}
}
But the funny thing is if i put the addres like "127.0.0.1" It works, but if i put the string addres it dosen't
You cannot bind to the external address that address belongs to the router.
You should bind to address 0.0.0.0 (all addresses) on your laptop and configure your router to forward the laptop port (or use UPnP).
The reason you cannot access your laptop directly is because your router, like most routers is a NAT (network address translation) router. It allows several computers to hide behind a single IP address. So the router will have a public IP address and your laptop and other devices behind the router will have a private IP address (such as those in the range 192.168.x.x)
Most NAT routers can be configured with static port forwarding; i.e. the port in a specific private address is reflected in the same or a different port in the public IP.
This allows access to internal devices from the public internet. UPnP is a protocol that does the same thing, but does not require manual configuration on the router. UPnP is usually how P2P applications and some multi-player games gain public accessible ports without human intervention. It is also why UPnP may be considered a security hazard since the computer owner may not be aware of such forwarding.
I have a library that handles reading and writing a cache file. This library is used by a Windows Service and several instances of a console application on the same machine. The console application runs when a user logs in.
I am getting occasional IO errors saying the cache file is in use by another process. I assume that collisions are occurring between the different application instances and service trying to read and write at the same time.
Is there a way to lock the file when it is in use and force all other requests to "wait in line" to access the file?
private void SaveCacheToDisk(WindowsUser user) {
string serializedCache = SerializeCache(_cache);
//encryt
serializedCache = AES.Encrypt(serializedCache);
string path = user == null ? ApplicationHelper.CacheDiskPath() :
_registry.GetCachePath(user);
string appdata = user == null ? ApplicationHelper.ClientApplicationDataFolder() :
_registry.GetApplicationDataPath(user);
if (Directory.Exists(appdata) == false) {
Directory.CreateDirectory(appdata);
}
if (File.Exists(path) == false) {
using (FileStream stream = File.Create(path)) { }
}
using (FileStream stream = File.Open(path, FileMode.Truncate)) {
using (StreamWriter writer = new StreamWriter(stream)) {
writer.Write(serializedCache);
}
}
}
private string ReadCacheFromDisk(WindowsUser user) {
//cache file path
string path = user == null ? ApplicationHelper.CacheDiskPath() :
_registry.GetCachePath(user);
using (FileStream stream = File.Open(path, FileMode.Open)) {
using (StreamReader reader = new StreamReader(stream)) {
string serializedCache = reader.ReadToEnd();
//decrypt
serializedCache = AES.Decrypt(serializedCache);
return serializedCache;
}
}
}
Sure, you could use a mutex and permit access only when holding the mutex.
You could use a cross-process EventWaitHandle. This lets you create and use a WaitHandle that's identified across processes by name. A thread is notified when it's its turn, does some work, and then indicates it's done allowing another thread to proceed.
Note that this only works if every process/thread is referring to the same named WaitHandle.
The EventWaitHandle constructors with strings in their signature create named system synchronization events.
One option you could consider is having the console applications route their file access through the service, that way there's only one process accessing the file and you can synchronise access to it there.
One way of implementing this is by remoting across an IPC channel (and here's another example from weblogs.asp.net). We used this technique in a project for the company I work for and it works well, with our specific case providing a way for a .net WebService to talk to a Windows Service running on the same machine.
Sample based on the weblogs.asp.net example
Basically what you need to do with the code below is create a Solution, add two Console Apps (one called "Server" and the other called "Client" and one Library to it. Add a reference to the Library to both console apps, paste the code below in and add a reference to System.Runtime.Remoting to both Server & Console.
Run the Server app, then run the client app. Observe the fact that the server app has a message passed to it by the client. You can extend this to any number of messages/tasks
// Server:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
namespace RemotingSample
{
public class Server
{
public Server()
{
}
public static int Main(string[] args)
{
IpcChannel chan = new IpcChannel("Server");
//register channel
ChannelServices.RegisterChannel(chan, false);
//register remote object
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemotingSample.RemoteObject),
"RemotingServer",
WellKnownObjectMode.SingleCall);
Console.WriteLine("Server Activated");
Console.ReadLine();
return 0;
}
}
}
// Client:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using RemotingSample;
namespace RemotingSample
{
public class Client
{
public Client()
{
}
public static int Main(string[] args)
{
IpcChannel chan = new IpcChannel("Client");
ChannelServices.RegisterChannel(chan);
RemoteObject remObject = (RemoteObject)Activator.GetObject(
typeof(RemotingSample.RemoteObject),
"ipc://Server/RemotingServer");
if (remObject == null)
{
Console.WriteLine("cannot locate server");
}
else
{
remObject.ReplyMessage("You there?");
}
return 0;
}
}
}
// Shared Library:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
namespace RemotingSample
{
public class RemoteObject : MarshalByRefObject
{
public RemoteObject()
{
Console.WriteLine("Remote object activated");
}
public String ReplyMessage(String msg)
{
Console.WriteLine("Client : " + msg);//print given message on console
return "Server : I'm alive !";
}
}
}
Check out the TextWriter.Synchronized method.
http://msdn.microsoft.com/en-us/library/system.io.textwriter.synchronized.aspx
This should let you do this:
TextWriter.Synchronized(writer).Write(serializedCache);