I am deploying my application in Tandem System (Unix environment). I am trying to connect to other application using TCP. I have a IP adress and Port number. from client (my application), I am writing data, looks like it's working (Not getting any Exception) but while reading data, I am getting ReadTimeOutException. Below is my program, I will appreciate your help. There is the same application which is return is C++ it's working fine with the same IP Address and Port number
Socket clientSocket = new Socket();
clientSocket.setKeepAlive(true);
clientSocket.setReuseAddress(true);
clientSocket.setTcpNoDelay(true);
clientSocket.setSoTimeout(120000);
clientSocket.setSendBufferSize(65535);
clientSocket.connect(new InetSocketAddress("Server IP", "Port Number"), 1000);
OutputStream outstream = clientSocket.getOutputStream();
outstream .writeInt(msgLen);
dout.write(msg, 0, msgLen);
dout.flush();
DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
int len = din.readInt();
data = new byte[len];
dis .readFully(data);
Its Throwing an Error while reading it.
Timeout while attempting to establish socket connection.
java.net.SocketTimeoutException: Read timed out
===========================
Socket clientSocket = new Socket();
clientSocket.setKeepAlive(true);
clientSocket.setReuseAddress(true);
clientSocket.setTcpNoDelay(true);
clientSocket.setSoTimeout(120000); // Should wait 3 minutes before throwing time out exception - Actually throwing after 2 minutes
clientSocket.setSendBufferSize(65535);
InputStream in= new ObjectInputStream(socket.getInputStream());
OutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.write(byteArray);
out.flush();
// Receive the same string back from the server
int totalBytesRcvd = 0; // Total bytes received so far
int bytesRcvd; // Bytes received in last read
while (totalBytesRcvd < byteArray.length) {
if ((bytesRcvd = in.read(byteArray, totalBytesRcvd,
byteArray.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection close prematurely");
totalBytesRcvd += bytesRcvd;
}
clientSocket .close(); // Close the socket and its streams
Please help me with this problem, I am stuck on this since last week.
Thank you!!!!
It isn't throwing that exception 'while attempting to establish the connection'. It is throwing it at some read call, almost certainly inside the constructor for ObjectInputStream. You should have included the stack trace in your question.
You need to create the ObjectOutputStream before the ObjectInputStream.
12000 milliseconds is two minutes, not three.
You should use readFully() at the client, just like you're doing in the server.
Related
I have a hardware that streams data to a windows server, and I have IP and port of this server. Now I want to connect unity app as a TCP client to this server. I have tried many solutions, but still have hard time to figure out best way to do this. Any help is highly appreciated. One issue that I have with current tutorials is that most of them define a unity server and try to connect another unity app as client and mostly based on localhost. However, I just want to connect a unity app as a TCP client to a server which I have IP and port.
Warm regards,
enter image description here
First of all, at the top of your script:
using System;
using System.Net.Sockets;
Then, create an instance of TcpClient and begin the connection:
socket = new TcpClient
{
// dataBufferSize is in bytes
ReceiveBufferSize = dataBufferSize,
SendBufferSize = dataBufferSize
};
socket.BeginConnect(ip, port, ConnectCallback, socket);
In ConnectCallback():
private void ConnectCallback(IAsyncResult asyncResult)
{
socket.EndConnect(asyncResult);
if (!socket.Connected) return;
// stream is a NetworkStream you should declare somewhere
stream = socket.GetStream();
// receiveBuffer is a byte[] you should declare somewhere
receiveBuffer = new byte[dataBufferSize];
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
In ReceiveCallback():
private void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
int byteLength = stream.EndRead(asyncResult);
if (byteLength <= 0)
{
// Disconnect client
return;
}
// Transfer data from receiveBuffer to data variable for handling
byte[] data = new byte[byteLength];
Array.Copy(receiveBuffer, data, byteLength);
// Handle data in any way you want to
// BeginRead again so you can keep receiving data
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
catch (Exception e)
{
Console.WriteLine($"Error receiving TCP data: {e.Message}");
}
}
I got this information from this tutorial.
Why can not I read bytes from the TcpClient in C#?
Here is the error I am getting:
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
Here is how I start my TcpClient:
public static async void Start()
{
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Loopback, 13000);
server.Start();
var client = await server.AcceptTcpClientAsync();
var stream = client.GetStream();
var bytes = Convert.FromBase64String("ABCD");
await stream.WriteAsync(bytes, 0, bytes.Length);
client.Close();
}
catch (Exception e)
{
throw;
}
finally
{
if(server != null)
{
server.Stop();
}
}
}
Here is how I run a request to the TcpClient:
try {
var response = (new HttpClient()).GetByteArrayAsync("http://localhost:13000").Result;
return Convert.ToBase64String(response);
} catch(Exception e) {
throw;
}
The return Convert.ToBase64String(response); line is never reached. While I see the quoted above error message inside the Exception e if I hit a breakpoint on the throw line.
Also, during debug the Start() method completes just fine. I.e. it starts, then wait for a request, gets a request, writes to the TclClient and at the end runs the server.Stop(); command.
I am expecting my code to work, because I took it and modified from the official documentation over here.
I tried to check out a few resources which would tackle my exception, but none of them did help.
E.g. I tried to use the question.
First answer tells nothing useful actually, but just plays around with words and at the end states that one can do nothing about the exception (please, correct me if I am missing a point in the answer).
And the second answer tells an impossible in my case problem. Because, I am sure there is nothing running on the 13000 port.
Your client code is using HttpClient, which sends an HTTP request and expects an HTTP response. But your server is not an HTTP server, it is just a plain TCP server, so the client is likely to fail and forcibly close the connection when it doesn't receive a properly formatted HTTP response.
The "official documentation" whose example you modified is not using HttpClient at all, it is using TcpClient instead.
If you want to use HttpClient in your client, then you should use HttpListener instead of TcpListener in your server.
I am opening a socket in jmeter (using groovy in JSR223 Sampler), and storing the message in a jmeter variable. This is the below code:
SocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getByName("localhost"),4801);
def server = new ServerSocket()
server.bind(inetSocketAddress)
while(!vars.get("caseId"))) {
server.accept { socket ->
log.info('Someone is connected')
socket.withStreams { input, output ->
InputStreamReader isReader = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isReader);
StringBuffer sb = new StringBuffer();
String str;
while((str = reader.readLine())!= null){
sb.append(str);
}
String finalStr = sb.toString()
String caseId = finalStr.split("<caseId>")[1].split("</caseId>")[0]
vars.put("caseId", caseId)
}
log.info("Connection processed")
}
}
if(vars.get("caseId"))
{
try
{
server.close();
vars.put("socketClose",true);
}
catch(Exception e)
{
log.info("Error in closing the socket: " + e.getMessage());
}
}
Now, there is some time delay between the first loop is executed and the message being recieved from the port. It doesnt receive the message immediately, and hence while loop is executed again. And then message is received and it sets caseId. It goes on to close the socket, because caseId is set. And that is throwing the error, because socket is still waiting for the message. So is there a way, to wait until socket has recieved all the messages, so i could properly close it?
Or just force close the socket, and Jmeter wont throw any exception?
Or when i execute next component, say IF controller in Jmeter, it waits until variable socketClose is set true? In that way, instead of while loops inside JSR223 sampler, i could use multiple If Controllers in Jmeter thread.
This is how ServerSocket.close() function works
public void close()
throws IOException
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
I don't think there is a way "to wait until socket has recieved all the messages" because Socket is dump as a rock and it can either listen for connections or shut down.
Maybe you might be interested in setSoTimeout() function?
Also this line:
vars.put("socketClose",true)
is very suspicious, I think you need to change it either to:
vars.put("socketClose", "true")
or to
vars.putObject("socketClose",true)
as JMeterVariables.put() function can accept only a String, see Top 8 JMeter Java Classes You Should Be Using with Groovy article for more details.
i have a trouble with my socket programming code.
when i use below:
var ipaddress = IPAddress.Parse("192.168.1.100");
IPAddress add = new IPAddress(ipaddress.GetAddressBytes());
TcpListener tcpListener = null;
tcpListener = new TcpListener(add, 53);
tcpListener.Start();
Console.WriteLine("Waiting for a connection...");
while (true)
{
Thread.Sleep(10);
TcpClient tcpClient = tcpListener.AcceptTcpClient();
//Read the data stream from the client.
byte[] bytes = new byte[512];
NetworkStream stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
SocketHelper helper = new SocketHelper();
helper.processMsg(tcpClient, stream, bytes);
}
i receive this error:
Additional information: Only one usage of each socket address (protocol/network address/port) is normally permitted
but i changed my cod to below :
static Socket sktListener;
var ipaddress = IPAddress.Parse("192.168.1.100");
IPAddress add = new IPAddress(ipaddress.GetAddressBytes());
sktListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(add, 53);
sktListener.Connect(ipLocal);
if (sktListener.Connected)
{
byte[] bytes = new byte[512];
int i = sktListener.Receive(bytes);
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
but it dose not any work. and stop on this line
int i = sktListener.Receive(bytes);
IPAddress.Parse() returns a new IPAddress object, you do not need to create a second IPAddress object from the first object's bytes:
IPAddress add = IPAddress.Parse("192.168.1.100");
Regarding the usage error in the first code, it means 192.168.1.100:53 is already in use by another socket.
Your second code is not creating a server, it is creating a client that connects to a server. Assuming these codes are meant to work together, then it makes sense why Receive() is blocking - your client is expecting to receive data that your server is not sending. Your server code is expecting a new client to send data, but your client is not sending anything.
A friend of mine came to me with a problem: when using the NetworkStream class on the server end of the connection, if the client disconnects, NetworkStream fails to detect it.
Stripped down, his C# code looked like this:
List<TcpClient> connections = new List<TcpClient>();
TcpListener listener = new TcpListener(7777);
listener.Start();
while(true)
{
if (listener.Pending())
{
connections.Add(listener.AcceptTcpClient());
}
TcpClient deadClient = null;
foreach (TcpClient client in connections)
{
if (!client.Connected)
{
deadClient = client;
break;
}
NetworkStream ns = client.GetStream();
if (ns.DataAvailable)
{
BinaryFormatter bf = new BinaryFormatter();
object o = bf.Deserialize(ns);
ReceiveMyObject(o);
}
}
if (deadClient != null)
{
deadClient.Close();
connections.Remove(deadClient);
}
Thread.Sleep(0);
}
The code works, in that clients can successfully connect and the server can read data sent to it. However, if the remote client calls tcpClient.Close(), the server does not detect the disconnection - client.Connected remains true, and ns.DataAvailable is false.
A search of Stack Overflow provided an answer - since Socket.Receive is not being called, the socket is not detecting the disconnection. Fair enough. We can work around that:
foreach (TcpClient client in connections)
{
client.ReceiveTimeout = 0;
if (client.Client.Poll(0, SelectMode.SelectRead))
{
int bytesPeeked = 0;
byte[] buffer = new byte[1];
bytesPeeked = client.Client.Receive(buffer, SocketFlags.Peek);
if (bytesPeeked == 0)
{
deadClient = client;
break;
}
else
{
NetworkStream ns = client.GetStream();
if (ns.DataAvailable)
{
BinaryFormatter bf = new BinaryFormatter();
object o = bf.Deserialize(ns);
ReceiveMyObject(o);
}
}
}
}
(I have left out exception handling code for brevity.)
This code works, however, I would not call this solution "elegant". The other elegant solution to the problem I am aware of is to spawn a thread per TcpClient, and allow the BinaryFormatter.Deserialize (née NetworkStream.Read) call to block, which would detect the disconnection correctly. Though, this does have the overhead of creating and maintaining a thread per client.
I get the feeling that I'm missing some secret, awesome answer that would retain the clarity of the original code, but avoid the use of additional threads to perform asynchronous reads. Though, perhaps, the NetworkStream class was never designed for this sort of usage. Can anyone shed some light?
Update: Just want to clarify that I'm interested to see if the .NET framework has a solution that covers this use of NetworkStream (i.e. polling and avoiding blocking) - obviously it can be done; the NetworkStream could easily be wrapped in a supporting class that provides the functionality. It just seemed strange that the framework essentially requires you to use threads to avoid blocking on NetworkStream.Read, or, to peek on the socket itself to check for disconnections - almost like it's a bug. Or a potential lack of a feature. ;)
Is the server expecting to be sent multiple objects over the same connection? IF so I dont see how this code will work, as there is no delimiter being sent that signifies where the first object starts and the next object ends.
If only one object is being sent and the connection closed after, then the original code would work.
There has to be a network operation initiated in order to find out if the connection is still active or not. What I would do, is that instead of deserializing directly from the network stream, I would instead buffer into a MemoryStream. That would allow me to detect when the connection was lost. I would also use message framing to delimit multiple responses on the stream.
MemoryStream ms = new MemoryStream();
NetworkStream ns = client.GetStream();
BinaryReader br = new BinaryReader(ns);
// message framing. First, read the #bytes to expect.
int objectSize = br.ReadInt32();
if (objectSize == 0)
break; // client disconnected
byte [] buffer = new byte[objectSize];
int index = 0;
int read = ns.Read(buffer, index, Math.Min(objectSize, 1024);
while (read > 0)
{
objectSize -= read;
index += read;
read = ns.Read(buffer, index, Math.Min(objectSize, 1024);
}
if (objectSize > 0)
{
// client aborted connection in the middle of stream;
break;
}
else
{
BinaryFormatter bf = new BinaryFormatter();
using(MemoryStream ms = new MemoryStream(buffer))
{
object o = bf.Deserialize(ns);
ReceiveMyObject(o);
}
}
Yeah but what if you lose a connection before getting the size? i.e. right before the following line:
// message framing. First, read the #bytes to expect.
int objectSize = br.ReadInt32();
ReadInt32() will block the thread indefinitely.