I'm writing a simple C++ client that should connect to a C# server. And, while the client runs throught fine and even states it sent a bunch of bites, the C# server never gets past listener.Acceppt():
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
I took the server source from here: Microsoft MSDN: Synchronous Server Socket Example
The client code I use can be found here: Microsoft MSDN: Complete Winsock Client Code
I also checked to server with the according C# client, which worked fine. I also checked the return values of the client, which also looked pretty plausible. So I'd guess the problem lies somewhere in how C++ / C# handle the details.
I tried Wireshark to find some hints, but mysteriously there was absolutely no trace of any communication on the used port (11000).
Where should I start looking to solve this issue?
Update: All communication at the moment runs just locally. I tried my IPAddress (from ipconfig) and 127.0.0.1 for both server and client.
I just have one network adapter installed, I use that IP adress. The client checks the getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result) and returns valid information (e.g. TCP as protocol). connect() returns 0, which should be ok.
Update 2:
I tried different combinations of C++/C# Server-Client-Setups:
C++-Server, C++ Client: Works
C++-Server, C# Client: Works
C#-Server, C# Client: Works
C#-Server, C++ Client: Does not work
C#-Server, putty: Works
Update 3: I tried Wireshark on the other Server-Client constellations, but neither of them did show any traffic on tcp.port == 11000, although they did work (see Update 2). It looks like Wireshark does not show any results, because everything is just local (see Wireshark localhost traffic capture)
I had the same problem.
The connection with winsock is asynchronous. And the example in C# that you are using is synchronous.
You have to use a Asynchronous example to get communication with your C++ code.
I used this two examples!
C Sharp server
https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx
C plus plus client
https://msdn.microsoft.com/en-us/library/windows/desktop/ms737591(v=vs.85).aspx
Related
Context
I made a SOCKS 5 Proxy implementation in C# based on the RFC 1928 specification as part of a software I'm working on. The proxy server will run locally inside my software (i.e. it's not on a remote server) and it will be used to redirect certain HTTP / HTTPS connections to a specific IP address.
How it should work / the reason for a local proxy
My software is sort of a launcher that launches a .jar file. The java program accepts optional parameters that specify a proxy server, and I want to exploit this feature to redirect any HTTP or HTTPS requests made by the java program to my own servers. This is why the proxy server MUST run on the same computer as the proxy client (the java program).
My problem
I am testing this proxy with a simple java program that tries to get a status code from a website through my proxy. For some reason, without modifying any code, approximately 8 times out of 10 the java program throws a SocketException (java.net.SocketException: Reply from SOCKS server has bad length), but at other times it works and properly prints out the HTTP response code.
What I've tried
If I run the proxy program on a separate computer or on a virtual machine, it always works without any errors (at least hopefully; I ran the java program ~20 times and it didn't throw the exception). This is not a viable solution in my case, because the proxy must run locally, as part of the program I'm working on.
My Code
The C# SOCKS implementation is too long for a SO post (~100 lines), so I have uploaded it to Pastebin.
The following is my java test code.
public static void main(String[] args) throws Exception {
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 32128));
HttpURLConnection conn = (HttpURLConnection)(new URL("http://somedomain.com/")
.openConnection(proxy));
conn.setDoInput(true);
conn.setDoOutput(false);
conn.connect();
System.out.println(conn.getResponseCode());
}
The Question
Why does the proxy server work if I host it on a separate computer / VM, but fail when I host (and use) it locally? And when it does work locally, what could be the cause of the seemingly random behavior, and how can I fix it?
EDIT:
I forgot to mention that the code currently only functions as a transparent proxy, i.e. it doesn't relay connections to other IP addresses yet.
I just revisited this project after a 6 months break, and I have found the solution to this problem. On lines 70-73 the first four bytes of the response are sent separately with writer.Write(...). I solved the problem by replacing those four lines with a single Write call that sends an array (byte[4]) containing the four values.
A. Description
I am using ZeroMQ monitor and I find that it works when logic disconnection but does not work when network broken down (unplug my cable).
For example:
I launch client app on an android pad, then launch a server app on my windows laptop. They are connected through a router with cables.
Everything will be OK with monitor if I close or open either client app or server app manually. Namely, the monitor on both sides can receive a 'Connect' or an 'Accept' and a 'Disconnect' event.
But If I unplug cable on the server side, while the client and server are connected and running, the monitors on both sides can not detect the 'Disconnect' event.
Is the monitor designed like this?
If so, are there any solutions to detect network broken down ( a cable unplug event ) except heartbeats?
If not, how to use the ZeroMQ's original monitor mechanism to solve this problem? Can a setTCPKeepAlive() interface be useful?
B. System environment
My scenario is as below.
Client
OS: Android, running on a pad, IDE: Android studio 2.3, lib:jeromq-0.4.3
// Java Code
String monitorAddr = "inproc://client.req";
ZContext ctx = new ZContext();
ZMQ.Socket clientSocket = ctx.createSocket(ZMQ.REQ);
clientSocket.monitor(monitorAddr,ZMQ.EVENT_ALL);
// Then start a montitor thread which is implemented by my own.
Server
OS: Windows 7 ( 64 bit ), running on my laptop, IDE: VS2013, lib: Clrzmq4
// C# Code
const string MonitorEndpoint = "inproc://server.rep";
var ctx = new ZContext();
var serverSocket = new ZSocket(ctx,ZSocketType.REP);
ZError error;
// Create serverSocket pair socket
if (!serverSocket.Monitor(MonitorEndpoint, ZMonitorEvents.AllEvents, out error))
{
if (error == ZError.ETERM)
return ; // Interrupted
throw new ZException(error);
}
// Create a monitor
ZMonitor _monitor = ZMonitor.Create(ctx, MonitorEndpoint);
_monitor.AllEvents += _monitor_AllEvents;
_monitor.Start();
AFAIK there is no built in heartbeat within ZeroMQ. I know there was some discussion on the topic within the ZMQ community some years ago, and that discussion may still be going on.
It is comparatively simple to incorporate your own heartbeat messaging in your application's use of ZeroMQ, especially if you use something like Google Protocol Buffers to encode different message types; the heartbeat is just another message.
Doing heartbeats in your application (rather than relying on some inbuilt mechanism) is ultimately more flexible; you can choose the heartbeat rate, you can choose what to do if the heartbeat fails, you can decide when heartbeating is important and not important, etc.
Consider heartbeats within a PUB/SUB pattern; it's a bit difficult for the ZMQ authors to decide on your behalf what connection / disconnection / connection-break events matter to you. And if they do build in a mechanism, but an application developer didn't want it, then it is a waste of bandwidth.
It's far easier for the ZMQ authors to leave that kind of application architectural issue to the application author (that's you!) to deal with.
With your specific example, an unplugged network cable simply looks (so far as any software can determine) like no traffic is flowing; it's the same as the application not sending anything. ZMQ doesn't send anything if the application hasn't sent anything.
If you look at the events that the socket monitor can report on, they're all the consequence of something flowing over the network connection, or something done to the socket by the application.
Trying to go lower than ZMQ protocol itself and access the TCP connection that specific ZeroMQ sockets use (while others do not) doesn't sound like a good idea; it would required to break encapsulation in multiple classes.
The answer #bazza gave in 2017 was entirely correct at the time.
However, newer versions of ZMQ (specifically ZMTP) include an heartbeat functionality.
Check ZMQ documentation for
socketOpt
Java functions
name
purpose
ZMQ_HEARTBEAT_IVL
get/setHeartbeatLvl()
heartbeat interval
milliseconds between ZMPT PINGs
ZMQ_HEARTBEAT_TIMEOUT
get/setHeartbeatTimeout()
local heartbeat timeout
how long the local socket waits between received packets until it considers the connection timed out
ZMQ_HEARTBEAT_TTL
get/setHeartbeatTtl()
remote heartbeat timeout
if and when remote side shall consider the connection timed out
ZMQ_HEARTBEAT_CONTEXT is still in draft state as of 2022. It is supposed to send an byte[] context with every ping.
Now, by design of ZMQ, quoting from chapter 2 of its documentation,
The network connection itself happens in the background, and ZeroMQ
will automatically reconnect if the network connection is broken
(e.g., if the peer disappears and then comes back).
Thus, answering your main question, I'd expect the monitor to give you ZMQ_EVENT_CONNECT_RETRIED / ZMQ_EVENT_CONNECTED events after the underlying connection was detected as disrupted.
Im building a multi client to server system using .Net for the client side and python for server side. Currently my python server socket simply echoes back the data sent to it without doing any extra processing:
from twisted.internet import reactor, protocol
class Echo(protocol.Protocol):
"""This is just about the simplest possible protocol"""
def dataReceived(self, data):
"As soon as any data is received, write it back."
self.transport.write(data)
print(str(data))
def main():
"""This runs the protocol on port 8000"""
factory = protocol.ServerFactory()
factory.protocol = Echo
reactor.listenTCP(8000,factory)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
Its built on the Twisted framework, and can be found on the examples page, at their website.
Im also using the Async TCP client for C# provided by MicroSoft found at:
https://msdn.microsoft.com/en-us/library/fx6588te%28v=vs.110%29.aspx
The problem is, the client sends the data successfully to the server - and the server receives it, and can echo it successfully, however the line:
self.transport.write(data)
Doesnt seem to send the data back correctly because the client never receives a reply back. Why is this happening? Is it a possible deadlock between reading streams?
I am currentry writing a C# client (with Mono using SSLStream) for an already existing OpenSSL server written in C++. I know that in theory, they should be able to communicate, but I always get an Exception:
Authentication or decryption has failed.
Which takes place in Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback when I invoke sslStream.AuthenticateAsClient(ServerName);
I do not need client authentication, so i don't use any client certificate, and i can't load my server certificate into a client's trust store, as I can't use the command line on the client side.
On the server, I seem to receive some random data, which should not happen, as I never invoke sslStream.Write() in the client code. Maybe I don't completely understand how the handshake happens. I have an OpenSSL C++ client that works perfectly though.
Does someone know How I could get this working?
I am using, on the server side, a self-signed certificate generated by OpenSSL, which i converted to DER format.
How I proceed:
Server side
Initialize OpenSSL
Load server certificate (DER) and private key (PEM)
Open a non-SSL listening socket
As a client connects, I open a new socket which I connect to an SSL_Bio and accept the connection
Read the SSL socket for incoming data.
Client side
I am trying to connect using a temporary client adapted from the one in this topic.
Open a new TCPClient
Link a new SSLStream to it with the same validation callback as in the thread above;
Calling AuthenticateAsClient(ServerName) which brings this exception.
Invoke sslStream.Write but the execution never gets here.
Any help would be greatly appreciated as I am not sure to understand how sslStream internally works.
Ok, got it. In fact, I was setting up the BIO and the SSL variables in the wrong order. You have to create and attach your BIO to your SSL BEFORE you actually call SSL_Accept in OpenSSL, otherwise the authentication cannot complete, which seems logical.
Also, I was using SSLStream in C# on client side to send my messages, while I was using BIO_read and BIO_write on the server Side with OpenSSL.
This could not work, because BIO_read and BIO_write are no equivalent to SSL_read and SSL_write. These two functions only read and write on the underlying socket, without any encryption or decryption, making the SSL handshake almost useless (aside from checking the identity of the other end of the line).
This explains why I was not able to engage communication as the two ends did not speak the same language: one sent unencrypted messages while the other expected SSL-wrapped messages and the other way round.
The SSL_read and SSL_Write functions take care of the encryption and decryption, so they are the ones to use here. Now it works perfectly.
If you need any further details about how I did that, please comment this answer.
I've installed memcached on Windows as a service, listening on the default port 11211. I know this works, because I can telnet to the server and carry out get / set commands without any problems.
I've then downloaded the Enyim Memcached client (Enyim.Caching.dll, version 2.7) and written a simple test program:
var mcc = new MemcachedClientConfiguration();
mcc.AddServer("127.0.0.1:11211");
mcc.SocketPool.ReceiveTimeout = new TimeSpan(0, 0, 10);
mcc.SocketPool.ConnectionTimeout = new TimeSpan(0, 0, 10);
mcc.SocketPool.DeadTimeout = new TimeSpan(0, 0, 20);
using (MemcachedClient client = new MemcachedClient(mcc))
{
client.Store(StoreMode.Set, "enyimtest", "test value");
Console.WriteLine(client.Get<string>("enyimtest"));
}
I know this connects to my server correctly, as calling the stats command in telnet shows an increase in the number of connections. However, it doesn't call get or set, as the cmd_get and cmd_set stats counters remain constant. The call to client.Get returns null.
The program does not error in any way. Does anyone know what could prevent the Enyim client from working in this situation?
EDIT:
Looks like this is caused by a timeout. Afer configuring log4net to capture the client's logging output, I found it contained the following (in addition to other stack trace items):
2010-12-17 14:26:37,579 [1] ERROR Enyim.Caching.Memcached.MemcachedNode [(null)] - System.IO.IOException: Failed to read from the socket '172.23.0.100:11211'. Error: TimedOut
2010-12-17 14:26:37,626 [1] WARN Enyim.Caching.Memcached.MemcachedNode.InternalPoolImpl [(null)] - Marking node 172.23.0.100:11211 as dead
I still don't understand why it is timing out though?
After an hour or so of playing around, I've found the answer. I used Wireshark to look at the network traffic to and from the server. I noticed that when using the Enyim client, the messages looked nothing like those when using telnet. In particular, I couldn't read the protocol commands going across the wire when using the Enyim client.
Therefore, I concluded that the Enyim client was using a different protocol.
A second protocol was added to the memcached server in version 1.4, which is the binary protocol. Prior to that, only the text protocol was supported. The latest Windows binary I can find for memcached is the one from Jellycan, and it is only version 1.2.6.
The Enyim client is configured to use the Binary protocol by default, which was just ignored by my server as it couldn't be understood.
I added the following line to my test program, and things started working immediately:
mcc.Protocol = MemcachedProtocol.Text;
I ran into the same issue above. I too struggled to find a newer version of memcached for Windows, but did find one eventually.
I've put links to the latest binaries along with other useful resources here.