How to simulate server down/available in java? - java

Our application has server/client side. The client supports both offline and online work mode.
So I need to test the client when server down, regain connective.
Question comes. How to simulate server down. Use codes to switch from down to ready, or from ready to down state.
Thanks in advance.
Joseph
update:
Actually, I could not extend the server interface to response the incorrect status. In my test scenario, the server is transparent. So incorrect url + port is a solution to do this.
But I could not modify the url when the session is valid. Another method is modify the hosts file to do this. I have to face the privilege issue in Windows.

Depends on what you mean by "server down". Possible options are:
Write a fake/dummy server that can return error messages corresponding to being down for test purposes.
Change the IP address of the server that your client looks for to a non-existing one so that it will think that the server is entirely down.

The basic idea is to mock the behavior of your server somehow. You could use mocking frameworks to do so.
You could also create manual mocks for testing purposes. Let the "proxy" of the server on the client implement this interface:
public interface IServer
{
bool foo();
}
You could create a "fake" implementation of that server and return whatever you'd like
public class FakeOfflineServer implements IServer
{
public bool foo()
{
// throw some exception here.
}
}
This approach allows you to fake different scenarios (no network connectivity, invalid credentials, etc.)
You could also use composition to switch from up to down in your tests:
public bool FakeServer implements IServer
{
private IServer offline = new FakeOfflineServer();
private IServer online = new Server();
public bool isUp = false;
private IServer getServer()
{
return isUp ? online : offline;
}
public bool foo()
{
return getServer().foo();
}
}

While testing server down, give any incorrect URL OR Port (Prefered). For recovery give the correct URL/Port.

This depends where you are testing. If you're unit testing, the best option is the mocking suggested by Bryan Menard.
If you're testing in an integration or production environment, You can actually cut the connection between you and the server.
Depending upon your operating system, you can do this in a number of ways.
For Windows based systems, Fiddler is fantastic. You can simulate almost anything, including delays on the requests and indeed just throwing requests away. It does not require admin access for Windows.
For linux based systems, one technique I've used in the past is to use a proxy server, or cut the port at operating system level. You can do this using iptables for instance:
To deny access to a particular port (25 in this case)
/sbin/iptables -I OUTPUT -p tcp --dest 127.0.0.1 --dport 25 -j DROP
and to allow it again:
/sbin/iptables --delete OUTPUT 1
You'll need root acces for this to work, but it does have the advantage that you don't need to touch your server or client configuration.

To emulate the server down case, you could write a ServerAlwaysDown class extending your actual server, but throwing ServerException (HTTP 500) for every connection.

If you want to be thorough use always the closest you have to a production environment for the tests, put client and servers in different machines and cut the connection, then restore it.

Related

PDF File Transfer from server to client: "java.io.IOException: An existing connection was forcibly closed by the remote host" [duplicate]

I am working with a commercial application which is throwing a SocketException with the message,
An existing connection was forcibly closed by the remote host
This happens with a socket connection between client and server. The connection is alive and well, and heaps of data is being transferred, but it then becomes disconnected out of nowhere.
Has anybody seen this before? What could the causes be? I can kind of guess a few causes, but also is there any way to add more into this code to work out what the cause could be?
Any comments / ideas are welcome.
... The latest ...
I have some logging from some .NET tracing,
System.Net.Sockets Verbose: 0 : [8188] Socket#30180123::Send() DateTime=2010-04-07T20:49:48.6317500Z
System.Net.Sockets Error: 0 : [8188] Exception in the Socket#30180123::Send - An existing connection was forcibly closed by the remote host DateTime=2010-04-07T20:49:48.6317500Z
System.Net.Sockets Verbose: 0 : [8188] Exiting Socket#30180123::Send() -> 0#0
Based on other parts of the logging I have seen the fact that it says 0#0 means a packet of 0 bytes length is being sent. But what does that really mean?
One of two possibilities is occurring, and I am not sure which,
The connection is being closed, but data is then being written to the socket, thus creating the exception above. The 0#0 simply means that nothing was sent because the socket was already closed.
The connection is still open, and a packet of zero bytes is being sent (i.e. the code has a bug) and the 0#0 means that a packet of zero bytes is trying to be sent.
What do you reckon? It might be inconclusive I guess, but perhaps someone else has seen this kind of thing?
This generally means that the remote side closed the connection (usually by sending a TCP/IP RST packet). If you're working with a third-party application, the likely causes are:
You are sending malformed data to the application (which could include sending an HTTPS request to an HTTP server)
The network link between the client and server is going down for some reason
You have triggered a bug in the third-party application that caused it to crash
The third-party application has exhausted system resources
It's likely that the first case is what's happening.
You can fire up Wireshark to see exactly what is happening on the wire to narrow down the problem.
Without more specific information, it's unlikely that anyone here can really help you much.
Using TLS 1.2 solved this error.
You can force your application using TLS 1.2 with this (make sure to execute it before calling your service):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Another solution :
Enable strong cryptography in your local machine or server in order to use TLS1.2 because by default it is disabled so only TLS1.0 is used.
To enable strong cryptography , execute these commande in PowerShell with admin privileges :
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
You need to reboot your computer for these changes to take effect.
This is not a bug in your code. It is coming from .Net's Socket implementation. If you use the overloaded implementation of EndReceive as below you will not get this exception.
SocketError errorCode;
int nBytesRec = socket.EndReceive(ar, out errorCode);
if (errorCode != SocketError.Success)
{
nBytesRec = 0;
}
Had the same bug. Actually worked in case the traffic was sent using some proxy (fiddler in my case). Updated .NET framework from 4.5.2 to >=4.6 and now everything works fine. The actual request was:
new WebClient().DownloadData("URL");
The exception was:
SocketException: An existing connection was forcibly closed by the
remote host
Simple solution for this common annoying issue:
Just go to your ".context.cs" file (located under ".context.tt" which located under your "*.edmx" file).
Then, add this line to your constructor:
public DBEntities()
: base("name=DBEntities")
{
this.Configuration.ProxyCreationEnabled = false; // ADD THIS LINE!
}
I've got this exception because of circular reference in entity.In entity that look like
public class Catalog
{
public int Id { get; set; }
public int ParentId { get; set; }
public Catalog Parent { get; set; }
public ICollection<Catalog> ChildCatalogs { get; set; }
}
I added [IgnoreDataMemberAttribute] to the Parent property. And that solved the problem.
If Running In A .Net 4.5.2 Service
For me the issue was compounded because the call was running in a .Net 4.5.2 service. I followed #willmaz suggestion but got a new error.
In running the service with logging turned on, I viewed the handshaking with the target site would initiate ok (and send the bearer token) but on the following step to process the Post call, it would seem to drop the auth token and the site would reply with Unauthorized.
Solution
It turned out that the service pool credentials did not have rights to change TLS (?) and when I put in my local admin account into the pool, it all worked.
I had the same issue and managed to resolve it eventually. In my case, the port that the client sends the request to did not have a SSL cert binding to it. So I fixed the issue by binding a SSL cert to the port on the server side. Once that was done, this exception went away.
For anyone getting this exception while reading data from the stream, this may help. I was getting this exception when reading the HttpResponseMessage in a loop like this:
using (var remoteStream = await response.Content.ReadAsStreamAsync())
using (var content = File.Create(DownloadPath))
{
var buffer = new byte[1024];
int read;
while ((read = await remoteStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await content.WriteAsync(buffer, 0, read);
await content.FlushAsync();
}
}
After some time I found out the culprit was the buffer size, which was too small and didn't play well with my weak Azure instance. What helped was to change the code to:
using (Stream remoteStream = await response.Content.ReadAsStreamAsync())
using (FileStream content = File.Create(DownloadPath))
{
await remoteStream.CopyToAsync(content);
}
CopyTo() method has a default buffer size of 81920. The bigger buffer sped up the process and the errors stopped immediately, most likely because the overall download speeds increased. But why would download speed matter in preventing this error?
It is possible that you get disconnected from the server because the download speeds drop below minimum threshold the server is configured to allow. For example, in case the application you are downloading the file from is hosted on IIS, it can be a problem with http.sys configuration:
"Http.sys is the http protocol stack that IIS uses to perform http communication with clients. It has a timer called MinBytesPerSecond that is responsible for killing a connection if its transfer rate drops below some kb/sec threshold. By default, that threshold is set to 240 kb/sec."
The issue is described in this old blogpost from TFS development team and concerns IIS specifically, but may point you in a right direction. It also mentions an old bug related to this http.sys attribute: link
In case you are using Azure app services and increasing the buffer size does not eliminate the problem, try to scale up your machine as well. You will be allocated more resources including connection bandwidth.
I got the same issue while using .NET Framework 4.5. However, when I update the .NET version to 4.7.2 connection issue was resolved. Maybe this is due to SecurityProtocol support issue.
For me, it was because the app server I was trying to send email from was not added to our company's SMTP server's allowed list.
I just had to put in SMTP access request for that app server.
This is how it was added by the infrastructure team (I don't know how to do these steps myself but this is what they said they did):
1. Log into active L.B.
2. Select: Local Traffic > iRules > Data Group List
3. Select the appropriate Data Group
4. Enter the app server's IP address
5. Select: Add
6. Select: Update
7. Sync config changes
Yet another possibility for this error to occur is if you tried to connect to a third-party server with invalid credentials too many times and a system like Fail2ban is blocking your IP address.
I was trying to connect to the MQTT broker using the GO client,
broker address was given as address + port, or tcp://address:port
Example: ❌
mqtt://test.mosquitto.org
which indicates that you wish to establish an unencrypted connection.
To request MQTT over TLS use one of ssl, tls, mqtts, mqtt+ssl or tcps.
Example: ✅
mqtts://test.mosquitto.org
In my case, enable the IIS server & then restart and check again.
We are using a SpringBoot service. Our restTemplate code looks like below:
#Bean
public RestTemplate restTemplate(final RestTemplateBuilder builder) {
return builder.requestFactory(() -> {
final ConnectionPool okHttpConnectionPool =
new ConnectionPool(50, 30, TimeUnit.SECONDS);
final OkHttpClient okHttpClient =
new OkHttpClient.Builder().connectionPool(okHttpConnectionPool)
// .connectTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(false).build();
return new OkHttp3ClientHttpRequestFactory(okHttpClient);
}).build();
}
All our call were failing after the ReadTimeout set for the restTemplate. We increased the time, and our issue was resolved.
This error occurred in my application with the CIP-protocol whenever I didn't Send or received data in less than 10s.
This was caused by the use of the forward open method. You can avoid this by working with an other method, or to install an update rate of less the 10s that maintain your forward-open-connection.

Netty Channel says remote address is "embedded". How can I find the originator?

I have a couple different very complex Netty 4 based processes that have lots of incoming and outgoing connections. In a certain case, I have about a dozen running on one machine.
I have my own handler and pipeline, and in the handler, I query the ChannelHandlerContext to log the remote end of a set of requests.
Normally I do something like this:
public void handle(ChannelHandlerContext ctx, HttpRequest request){
System.out.println(ctx.getChannel().getRemoteAddress());
}
In this case, the remote address is of type EmbeddedSocketAddress, and returns just "embedded".
In normal cases, I can get the IP/Port from the InetSocketAddress and use lsof to find out who's making the call. In this case, I can't.
How can I find out what/who is calling into my handler?
Ok, so I found out where these are coming from. The framework that creates my pipeline runs a "warm up" routine that injects these requests right into the pipeline without a remote end. I apologize for my idiocy.

Java rmi over the internet

I am developing a game in Java using RMI for all network communication. RMI allows me to call method on my server, but it is not enough for me. I also want the server to be able to spread message among connected clients.
My clients look up for the server (it's interface extends Remote) and register on it. It allows the server to know who is connected. My clients also implement an interface that extends Remote. Here is some part of my code:
Interfaces declaration:
public interface IServer extends Remote {
void connect(IClient Client) throws RemoteException, ExistingItemException;
//...
}
public interface IClient extends Remote {
public void notify(Notification Notification) throws RemoteException;
//...
}
Server side:
//int RMIPort = 1099, ServerPort = 1100;
IServer Server = new RMIServer();
IServer Proxy = (IServer) UnicastRemoteObject.exportObject(Server, ServerPort);
LocateRegistry.createRegistry(RMIPort).rebind("//" + LocalIP + ":" +
RMIPort + "/xxx", Proxy);
Client side:
//Sets the local reference to IServer and creates the IClient
setInstance(new Client(Login, (IServer) LocateRegistry.getRegistry(RemoteIP).
lookup("//" + RemoteIP + ":" + RMIPort + "/xxx")));
//Gets the IClient and makes it available for the IServer to call notify(...)
Proxy.connect((IClient) (UnicastRemoteObject.exportObject(getInstance(), 0)));
This solution works in local but doesn't when I'm trying to use it through Internet.
I have setup my router to expose my computer to a fix IP address and forward the 1099 and 1100 ports. This solution allow other developers to "lookup" my server and get a valid and usable Proxy, but it doesn't allow them to export their IClient. It seems that the JVM tries to export the object to their local network and the execution stops here.
So, I have tried to pass -Djava.rmi.server.hostname=my-external-IP JVM argument both local for my server and remote for clients. Doing so, exportObject throws a ConnectException to the remote ip instead of local one.
Forget it. Using callbacks over the Internet requires every client to configure his firewall/NAT box/whatever to allow inbound connections and probable port forwarding. Many of them aren't configurable at all, and many of them are run by net admins who just won't do it.
NB you would also have to export on a fixed port.
There is an alternative:
http://dev.root1.de/projects/simon/wiki#Why-SIMON-is-better-than-
The protocol is not compatible to RMI, but the usage is almost the same. Changing from RMI to SIMON is typically not that hard. I heared from users that switching to SIMON took just 30min.
You might think about alternative solution than using RMI, because I believe it was designed for Intranet applications (i.e. Enterprise application within a local network) not Internet.
I would suggest using a long-running TCP connection between the client and the server so at any moment the server wants to communicate back it just pushes a message to this connection.
In this case, initiating the connection will always be the client task. It is very similar to how mail clients connects to imap or pop3 server.

FIX protocol using java

I have developed a utility in Java using the Financial Information eXchange(FIX) protocol to pull data from an input stream. However, I currently have not found any test servers online to which I can connect to that implement the FIX protocol. Could someone please let me know how I can achieve this?
http://www.quickfixj.org/ have an open source fix engine. It comes with an example that has a simple server. You might want to use their library for the client too rather than rebuilding a FIX engine from scratch...
You can use CoralFIX to quickly fire up a test server. It takes care of all the session level FIX messages, such as Logon, ResendRequest, SequenceReset, Heartbeat so you are ready to start exchanging messages with your client. Below a simple example:
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;
public class SimpleFixApplicationServer extends FixApplicationServer {
public SimpleFixApplicationServer(NioReactor nio, int port, Configuration config) {
super(nio, port, config);
}
#Override
protected void handleFixApplicationMessage(Client client, FixMessage fixMsg, boolean possDupe) {
// do whatever you want to do with the application message received from this client...
}
public static void main(String[] args) {
NioReactor nio = NioReactor.create();
MapConfiguration config = new MapConfiguration();
// print all messages received and sent to STDOUT for debugging purposes
// (default is false)
config.add("debugMessages", "true");
// accept as the client inbound sequence whatever
// sequence I receive in the first message coming from the client
// (default is false)
config.add("acceptInboundSeqFromClient", "false");
Server server = new SimpleFixApplicationServer(nio, 45451, config);
server.open();
nio.start();
}
}
A full explanation of the code above can be found here.
Disclaimer: I am one of the developers of CoralFIX.
I assume you haven't built it in a vacuum, but rather to talk to some broker's FIX server? If that's the case, speak to your broker as they are likely to have a test server you could connect to.
It depends if you want a hosted or a DIY solution. If you want to quickly bring up a FIX sessions without having to compile/build/setup then I would go for a hosted simulator.
We have an account with these guys http://www.fixsim.com/ and would recommend them (simple to setup and add more connections).
(I don't work for the company and get nothing to say this)
you can try to search more information here: http://fixprotocol.org/discuss/
I work for a broker, and you're more than welcome to connect to our Staging FIX servers. I do not know of any anonymous servers around, perhaps this is something the FIX community could set up..
Cheers,
Chris

What is the quickest way to detect an unreachable host in Java?

I would like the fastest and most accurate function boolean isReachable(String host, int port) that passes the following JUnit tests under the conditions below. Timeout values are specified by the JUnit test itself, and may be considered "unreachable."
Please note: All answers must be platform-independent. This means that InetAddress.isReachable(int timeout) is not going to work, since it relies on port 7 to do a ping on Windows (ICMP ping being an undocumented function on Windows), and this port is blocked in this setup.
LAN Setup:
thisMachine (192.168.0.100)
otherMachine (192.168.0.200)
no machine is called noMachine or has the IP 192.168.0.222 (always unreachable)
both machines are running Apache Tomcat on port 8080; all other ports are unreachable (including port 7)
example.com (208.77.188.166) is running a webserver on port 80 and is only reachable when the LAN is connected to the Internet
Occasionally, the LAN is disconnected from the Internet in which case only local machines called by IP address are reachable (all others are unreachable; there's no DNS).
All tests are run on thisMachine.
#Test(timeout=1600) // ~320ms per call (should be possible to do better)
public void testLocalhost() {
// We can always reach ourselves.
assertTrue(isReachable("localhost", 8080));
assertTrue(isReachable("127.0.0.1", 8080));
assertTrue(isReachable("thisMachine", 8080)); // Even if there's no DNS!
assertTrue(isReachable("192.168.0.100", 8080));
assertFalse(isReachable("localhost", 80)); // Nothing on that port.
}
#Test(timeout=5500) // ~1867ms per call (should be able to do better)
public void testLAN() {
assertTrue(isReachable("192.168.0.200", 8080)); // Always connected to the LAN.
assertFalse(isReachable("192.168.0.222", 8080)); // No such a machine.
assertFalse(isReachable("noMachine", 8080)); // No such machine.
}
The following test is only run when the LAN is disconnected from the Internet.
#Test(timeout=5600) // ~1867ms per call (reasonable?)
public void testNoDNS() {
assertFalse(isReachable("otherMachine", 8080)); // No DNS.
assertFalse(isReachable("example.com", 80)); // No DNS & no Internet.
assertFalse(isReachable("208.77.188.166", 80)); // No Internet.
}
The following test is only run when the LAN is connected to the Internet.
#Test(timeout=5600) // ~1867ms per call (reasonable?)
public void testHaveDNS() {
assertTrue(isReachable("otherMachine", 8080)); // DNS resolves local names.
assertTrue(isReachable("example.com", 80)); // DNS available.
assertTrue(isReachable("208.77.188.166", 80)); // Internet available.
}
Firstly you need to recognise that you have potentially conflicting requirements; IP sockets are not time deterministic. The quickest you can ever detect unreachability is after your elapsed timeout. You can only detect reachability quicker.
Assuming reachability/isReachable is your real objective, you should just use a straightforward non-blocking socket IO as shown in the Java Ping simulator, the example connects to the time service but would work equally well on 8080.
If you want to test whether you can connect to a web server you could also create a URL based on the host name and the port number and use that to create a URLConnection checking the result (including exceptions) of the connect method should tell you whether the webserver is reachable.
Not sure how practical this is.
How about doing the equivalent of traceroute(tracert on windows) and once you get a success, you can proceed.
In corporate networks, I've seen ICMP(ping) blocked by admins BUT usually, tracert still works. If you can figure out a quick way to do what tracert does, that should do the trick ?
Good luck!
My most recent solution depends using a TimedSocket (source code) with 3000ms timeout while performing a connect.
Timings:
1406ms : testLocalHost()
5280ms : testLAN()
Can't even get these to work properly:
testNoDNS()
testHaveDNS()
If you need to do this with a seriously large number of hosts in a very brief period of time, I'd consider using a tool like fping instead- shell out to exec it and parse the output when it comes back. fping runs a large number of parallel queries at once, so you could theoretically check a few thousand hosts in a minute (I think the limit is 4096?)
The rate determining step for host availability is not within your own code, but in the netlag. You must wait for the host to respond, and this can take time. If your program blocks while waiting for a response it could be a problem. I got around this by creating each host as an object, each with its own threaded method for checking availability. In my own situation I have 40 hosts I keep track of. My main program loops through an array of 40 machine objects once every 20 seconds, calling the appropriate method on each to check availability. Since each machine object spawns its own thread to do this, all 40 machines are interrogated concurrently and the (up to 500ms) response time for each isn't a problem.

Categories

Resources