is it necessary for the socket to immediately receive data/java - java

I am working on a network simulation in java. I send data from the server side to the client side. The client receives this data and then client starts to read data which has come into its own buffer and shows it on the client terminal that how much data has arrived further "whereas" on the server side, it keep sending data. Receiving statements are also written on the client side but the client is busy in reading in its buffer. After it finishes, it receives data from server. Sometimes, when I run the program, the data sent from the server is not read and exception occurs "Connection reset". Is it timing issue? Should the data sent from server be immediately received at client side? or due to some other reason?
Here is the server's side code:
soc.sendHP_Grant(grantSizeHP2); //soc is the socket's object
soc.sendLP_Grant(grantSizeLP2);
soc.sendGrant_info(grantStartTime);
soc.sendGrant_info(grantEndTime);
whereas on the client side:
receivedGrant_HP = socOnu.receiveReportHP();
receivedGrant_LP = socOnu.receiveReportLP();
startTime = socOnu.receiveGrant_Info();
endTime = socOnu.receiveGrant_Info();
onu2.accessTraffic("ONU2-Traffic-report-2.txt");
After that, I am again using the server's side code to send further data and then again I use client's side code to receive data. According to me, it's happening because I am not immediately receiving data at client side. Please mention the solution or if there is some other reason. Please mention with solution. Thanks in advance
This is the code which (is causing problem) I am using for receiving data at client side:
public double receiveReportHP() throws IOException{
DataInputStream dis = new DataInputStream(socket.getInputStream());
double reportHP = dis.readDouble(); //exception on this line
return reportHP;
}
whereas the sending side code is (working fine):
public double receiveReportForHP() throws IOException{
DataInputStream dis = new DataInputStream(socket.getInputStream());
double reportHP = dis.readDouble();
return reportHP;
}

Related

After multithreaded server converted to SSL, problem echoing back messages

I have a multithreaded chat server that I have converted to work with Java SSL sockets. You can see the version without SSL sockets compared to the one I converted here, on Github. (Master branch has SSL, other branch has regular sockets)
This original model (without SSL) uses "ServerThreads" controlled by the Client to communicate with other Clients by sending messages to their "ClientThreads" on the server side, which then will echo their messages out to all other ServerThreads.
Here is the run method of ServerThread_w_SSL (client side)
#Override
public void run(){
System.out.println("Welcome :" + userName);
System.out.println("Local Port :" + socket.getLocalPort());
System.out.println("Server = " + socket.getRemoteSocketAddress() + ":" + socket.getPort());
//setup handshake
socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
try{
PrintWriter serverOut = new PrintWriter(socket.getOutputStream(), false);
InputStream serverInStream = socket.getInputStream();
Scanner serverIn = new Scanner(serverInStream);
// BufferedReader userBr = new BufferedReader(new InputStreamReader(userInStream));
// Scanner userIn = new Scanner(userInStream);
socket.startHandshake();
while(!socket.isClosed()){
if(serverInStream.available() > 0){
if(serverIn.hasNextLine()){
System.out.println(serverIn.nextLine());
}
}
if(hasMessages){
String nextSend = "";
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.println(userName + " > " + nextSend);
serverOut.flush();
}
}
Here is the run method of ClientThread_w_SSL (server side)
#Override
public void run() {
try{
// setup
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
Scanner in = new Scanner(socket.getInputStream());
//setup handshake
socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
socket.startHandshake();
// start communicating
while(!socket.isClosed()){
if(in.hasNextLine()){
String input = in.nextLine();
// NOTE: if you want to check server can read input, uncomment next line and check server file console.
System.out.println(input);
for(ClientThread_w_SSL thatClient : server.getClients()){
PrintWriter thatClientOut = thatClient.getWriter();
if(thatClientOut != null){
thatClientOut.write(input + "\r\n");
thatClientOut.flush();
}
}
}
}
The original program works with regular sockets, but after converting to SSL sockets, I encountered a problem: input is not being echoed back from the ClientThreads (server side) to the ServerThreads (client side).
In my first attempt at converting to SSL I used certificates, keystores and truststores. I encountered the same problem then as I do here without them, instead only using the default socket factory which relies on the cacerts file that comes with the JDK.
Note that before this bug was encountered, the first problem to address was the handshake failure occurring between the client and server. Because of the way SSL and the Java PrintWriter class work, the handshake gets initiated the first time PrintWriter.flush() is called, which happens as soon as the client sends a chat message to the server. This is only resolved by manually enabling supported ciphersuites in both the ClientThread (server) and ServerThread (client), then calling SSLSocket.StartHandshake() in at least the ClientThread, if not both.
Now the server is receiving messages from the client, but it is not echoing them out to the clients.
When I run it in a debugger and try stepping through the code I find that the ClientThread receives the client's message and sends it back by calling write() on the PrintWriter for each ClientThread, then flush(). The ServerThread is supposed to receive it by calling InputStream.available() to check for input without blocking, but available() always returns '0 bytes' and so it never hits Scanner.nextLine()
So either Printwriter.write() and .flush() aren't sending data or InputStream.available() is not reading data.
EDIT: After more debugging and testing, I can only narrow the problem down to output from the server side. I determined this by having the server immediately send its own message before waiting to receive messages, and had the client just grab the nextLine() instead of checking first with available(). Since this test failed it shows that data must be being blocked somehow coming from the server side only.
EDIT 2: I changed the code to use ObjectInputStreams and ObjectOuputStreams instead of using the Scanner and PrintWriters. Now I'm sending "Message" objects from a Serializable class I made to just hold Strings. This has fixed the output issue for messages coming from the server. If I make the client simply wait for input by calling readObject() it will receive messages from the server. However, if I use the availble() method of InputStream first, it still only returns 0 even when it shouldn't. Since the InputStream serverInStream is initialized by socket.getInputStream(), it gets an ssl.AppInputStream with an ssl.InputRecord, and I'm guessing one of the two does not implement available() correctly.
I figured it out: the problem was available(), It is useless with SSL in Java. I got the solution from this answer.

Indefinite stale of TCP packet reception

Deplyment environment:
I have created a TCP server using JAVA over windows 10 OS. My TCP client program is written in VC++ and runs on windows 7 OS (I don't have any control over this part of the code, it is a black box to me).
My TCP server code is like this:
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
Following is the TCP connection handler snippet:
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
The communication is packet based and the protocol/parsing is handled by packetHandler.
Two more variant I've tried:
I have tried to close the socket as and when a reply is sent back to the client. That is, after receiving one packet of data, I reply to the client and close the connection.
I used inputStream.available before using the read method.
The problem I face:
Most of the time the TCP server replies to incoming packets within a second. If the server receives a packet after some idle time, the server doesn't reply to the packet. Sometimes even when there is active communication is going on, the reply is not being transmitted. Secondly, the isConnected function returns true even when the client socket closed the connection.
Debugging attempts:
I used teraterm to send packets and checked it. The behavior is same. As long as I send packets one after another, I don't have an issue. If one packet doesn't get a reply, then every packet sent after that does not get reply from the server.
When I press Ctrl+C in server console, all the packets sent from teraterm is processed by TCP server and reply is sent back. After this the server works properly for some duration.
I checked the packet flow with wireshark. When the replies are sent back normally, it is sent along with the ACK of client request (SYN, SYN+ACK, ACK, PSH, PSH+ACK, FYN, FYN+ACK, ACK). When the reply gets staled (may not be the right term, it is stuck in inputStream.available or inputStream.read), only ACK packet is sent by server (SYN, SYN+ACK, ACK, PSH, ACK).
I checked many forums and other threads in stackexchange, learned about Nagle's algorithm, applicaion must take care of packetization in TCP, TCP may receive 10+10 packets as 8+12 or 15+5 or any such manner. The server code takes care of packetization, setKeepAlive is set to true (there is no problem when a packet is sent from server).
Problem in short: "At times, TCP read call is getting blocked for a long duration even when there is incoming packets. When Ctrl+C is pressed, they are getting processed."
PS: I just started posting queries on stackexchange, so kindly let me know if there is any issues in the way of formulating the query.
PPS: Sorry for such a long post.
UPDATE
The comment from EJB helped me to identify the peer disconnect.
I made another setup with Ubuntu 16.04 as operating system for server. It has been 3 days, windows system had the issue occasionally. Ubuntu 16.04 never staled.
Some things to consider;
the TCP buffer sizes are usually 8K at least and I don't think you can skink them to 2000 bytes, or if you can, I don't think it's a good idea.
the size of the byte[] doesn't really matter over about 2K, you may as well pick a value.
you can't need to be creating a buffer more than once.
So in short I would try.
Socket s = ss.accept();
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
and
try {
InputStream in = this.clientSocket.getInputStream();
OutputStream out = this.clientSocket.getOutputStream();
int bufferLen = 0;
byte[] buffer = new byte[2048];
while ((bufferLen = in.read(buffer)) > 0) {
out.write(buffer, 0, bufferLen); // not buffered so no need to flush
}
} finally {
this.clientSocket.close();
}
At times, TCP read call is getting blocked for a long duration even when there is incoming packets.
Would write a test Java client to see that this is not due to behaviour in Java.

C# TcpClient to netty not always arriving

Me and a friend are working on a project which requires us to communicate between a C#.NET application and a Java application.
We're using the TcpClient and BinaryWriter classes on the .NET side of things to send and receive things. We're using code similar to this to send things:
byte[] content = //we're getting our content here
Writer.Write(new byte[9]); //this is the BinaryWriter with the NetworkStream of the TcpClient
Writer.Flush();
On the Java side of things, we're using netty to handle our networking. To receive the content we send from the .NET side, we add a ChannelInboundHandlerAdapter to the pipeline and use the channelRead method to read the content:
public void channelRead(ChannelHandlerContext ctx, Object received)
{
ByteBuf receivedByteBuf = (ByteBuf)received;
this.bytesRead = receivedByteBuf.readableBytes();
System.out.println("Received " + this.bytesRead + " bytes.");
final byte[] buffer = new byte[this.bytesRead];
receivedByteBuf.markReaderIndex();
receivedByteBuf.readBytes(buffer);
receivedByteBuf.resetReaderIndex();
}
Now the strange thing is, that when we try sending content, it doesn't always arrive in one piece. Sometimes we only receive all but some bytes we originally sent, which arrive in a new call of channelRead. In this example, only 6-8 bytes would arrive. This is very strange, as this only happens when using .NET. We tried sending content using python and everything worked fine and it arrived in one channelRead call.
import socket
import string, random
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 8888))
s.send(''.join(random.choice(string.lowercase) for x in range(500)))
s.close()
Unfortunately, the nature of our project prevents us from changing our Java networking library, so we're stuck with netty.
Did we miss some setting in netty or does this have to do with the nature of the .NET TCP libraries? We would appreciate any help we can get.

Java(client) and C#(Server) TCP Socket. and Server read infinite last data from client

Java(client) and C#(Server) TCP Socket. and Server read infinite last data from client(Java)
I has been search for entire day already, its weird.
I created 2 client: Java(real), C#(for testing)
like this:
Java(Real):
Socket socket = new Socket(SyncActivity.ip,SyncActivity.port);
DataOutputStream out;
out = new DataOutputStream(socket.getOutputStream());
String s = "Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$";
out.write(s.getBytes(),0,s.getBytes().length);
out.flush();
s = "Yes this another data$";
out.write(s.getBytes(),0,s.getBytes().length);
out.flush();
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
Thread.currentThread().interrupt();
and
C#(for testing)
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect("192.168.0.138", 11838);
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
On C#(testing) side, sent one data to server, and server readed the data once and blocked to wait another data.(second data same as reading it once and blocked)I just want like this.
On Java(Real)side, sent two data to server and server reading 1st data once and read same 2nd data forever. Java side is verified sent only once.
It is full data I was received. Why? its weird.
result as:
on C#(testing)
Client request connection.
Server accept and created connection.
Server try Read (and Blocked)
Client send >> TextBox
Server received >> TextBox
Server try Read (and Blocked)
but on Java(Real):
Client request connection.
Server accept and created connection.
Server try Read (and Blocked)
Client send >>
Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Server received >>
Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Client send >> Yes this another data
Server try Read
Server received >> Yes this another data
Server try Read
Server received >> Yes this another data
Server try Read
Server received >> Yes this another data
Server try Read
Server received >> Yes this another data
Server try Read
Server received >> Yes this another data
Server try Read
Server received >> Yes this another data
(and forever and forever)
Server code:
TcpListener serverSocket = new TcpListener(IPAddress.Any, Convert.ToInt16(Ini.IniReadValue("About", "ServerPort", "MVS_VAN.info")));
TcpClient clientSocket = default(TcpClient);
serverSocket.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
serverSocket.Stop();
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[128000];
do
{
Socket soc = clientSocket.Client;
soc.Receive(bytesFrom);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
MessageBox.Show("", dataFromClient);
networkStream.Flush();
//networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
//string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
//dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
//tried ^ this 3 line also.
} while ((true));
clientSocket.Close();
serverSocket.Stop();
The server is ignoring the count returned by Receive(). It is therefore (a) ignoring endi of stream and (b) processing invalid data in the buffer.
Im found what is the problem after a day investigate.
but its still weird:
on Java Client:
socket.close();//<--here causing a start of server read same last data infinitly
it was not closing it properly. maybe where protocol is still close_wait state to ensure all packets is arrived to server?
.
fake resolve:
Im write my own command packets send to server like "cmd_request_close_connection", and close the connection on server side when server receive packet like this.

purpose of socket.shutdownOutput()

I am using the below code to send data to a tcp server. I am assuming that I need to use socket.shutdownOutput() to properly indicate that the client is done sending the request. Is my assumption correct? If not please let me know the purpose of shutdownOutput(). Also appreciate any further optimizations I can make.
Client
def address = new InetSocketAddress(tcpIpAddress, tcpPort as Integer)
clientSocket = new Socket()
clientSocket.connect(address, FIVE_SECONDS)
clientSocket.setSoTimeout(FIVE_SECONDS)
// default to 4K when writing to the server
BufferedOutputStream outputStream = new BufferedOutputStream(clientSocket.getOutputStream(), 4096)
//encode the data
final byte[] bytes = reqFFF.getBytes("8859_1")
outputStream.write(bytes,0,bytes.length)
outputStream.flush()
clientSocket.shutdownOutput()
Server
ServerSocket welcomeSocket = new ServerSocket(6789)
while(true)
{
println "ready to accept connections"
Socket connectionSocket = welcomeSocket.accept()
println "accepted client req"
BufferedInputStream inFromClient = new BufferedInputStream(connectionSocket.getInputStream())
BufferedOutputStream outToClient = new BufferedOutputStream(connectionSocket.getOutputStream())
ByteArrayOutputStream bos=new ByteArrayOutputStream()
println "reading data byte by byte"
byte b=inFromClient.read()
while(b!=-1)
{
bos.write(b)
b=inFromClient.read()
}
String s=bos.toString()
println("Received request: [" + s +"]")
def resp = "InvalidInput"
if(s=="hit") { resp = "some data" }
println "Sending resp: ["+resp+"]"
outToClient.write(resp.getBytes());
outToClient.flush()
}
I am using the below code to send data to a tcp server. I am assuming
that I need to use socket.shutdownOutput() to properly indicate that
the client is done sending the request. Is my assumption correct?
YES Your assumption is correct. And this output ShutDown is known as half close . Using half close the TCP provides the ability for one end of the connection to terminate its output, while still receiving data from the other end. Let me walk you through the effects of socket.shutdownOutput() method :
Locally, the local socket and its input stream behave normally for reading
purposes, but for writing purposes the socket and its output stream behave
as though the socket had been closed by this end: subsequent writes to the
socket will throw an IOException
TCP’s normal connection-termination sequence (a - FIN acknowledged by
an ACK) is queued to be sent after any pending data has been sent and acknowledged.
Remotely, the remote socket behaves normally for writing purposes, but for
reading purposes the socket behaves as though it had been closed by this
end: further reads from the socket return an EOF condition, i.e. a read count
of -1 or an EOFException , depending on the method being called.
When the local socket is finally closed, the connection-termination sequence
has already been sent, and is not repeated; if the other end has already
done a half-close as well, all protocol exchanges on the socket are now
complete.
Hence we see that When the EOF is received, that end is assured that the other end has done the output shutdown. And this scenario is perfectly achieved by socket.shutDownOutput() on the other side.
Source: Fundamental Networking in Java, Esmond Pitt
Socket.shutdownOutput() means that the client is finished sending any data through the TCP connection. It will send the remaining data followed by a termination sequence which will completely close its OUTGOING connection. It is not possible to send any further data, which will also indicate to your program that the request is completely finished. So its recommended if you are sure you don't have to send any more data.
But it's not needed to indicate that the request is finished (you don't have to open/close the output all the time if you have multiple requests), there are other ways.

Categories