I want to read and write byte[] data with a socket, but I cannot stop the stream.
This is my server:
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("Welcome to Server side");
DataInputStream in;
DataOutputStream out;
ServerSocket servers = null;
Socket fromclient = null;
// create server socket
try {
servers = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Couldn't listen to port 4444");
System.exit(-1);
}
try {
System.out.print("Waiting for a client...");
fromclient = servers.accept();
System.out.println("Client connected");
} catch (IOException e) {
System.out.println("Can't accept");
System.exit(-1);
}
in = new DataInputStream(fromclient.getInputStream());
out = new DataOutputStream(fromclient.getOutputStream());
String input = "", output;
System.out.println("Wait for messages");
byte[] bytes = new byte[16*1024];
int count;
while ((count = in.read(bytes)) > 0) {
byte[] mass = "some data".getBytes("UTF-8");
out.write(mass, 0, count);
System.out.println(Arrays.toString(bytes));
}
out.close();
in.close();
fromclient.close();
servers.close();
}
}
When I receive data from the client it opens an infinite stream which doesn't stop.
How can I stop this DataInputStream?
Close the connection from the client side (or server side). As long as the connection is open, the server will wait for data to be sent.
In a proper setup you would have a well defined protocol, which could then include shutdown messages to inform the server when the client decides to disconnect. Simply closing the connection is a "raw" way to achieve that, but it's not very elegant.
Related
I am trying to create a Modbus setup as follows:
client <----> IED <----> Modbus Server
IED has the IP 192.168.x.x and Modbus Server uses localhost as IP. All entities are in the same VM. The client is supposed to send a request to the IED,the IED forwards it to the server and the server responds to the IED.
The problem is the IED receives the request from the master which is stored in a byte array but transmitting the request to the server does not work. Wireshark traces show that the TCP connection is established with the server but request is not transmitted.
See the code below:
public class App {
public static void main(String[] args) {
IEDServer iedServer = new IEDServer();
iedServer.start(502);
}
}
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
public class IEDServer {
private ServerSocket serverSocket;
public void start (int port){
try {
InetAddress inetAddress = InetAddress.getByName("192.168.20.138");
serverSocket = new ServerSocket(port, 1024, inetAddress);
while (true){
new ClientHandler(serverSocket.accept()).start();
System.out.println("Connection accepted");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop(){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
import java.net.Socket;
public class ClientHandler extends Thread{
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
public ClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
//connection from client
out = new DataOutputStream (clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
// in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// String readline;
//for connection to modbus server
Socket modbusSocket = new Socket("127.0.0.1",502);
modbusSocket.setSoTimeout(10000);
DataOutputStream modbus_out = new DataOutputStream (clientSocket.getOutputStream());
DataInputStream modbus_in = new DataInputStream(clientSocket.getInputStream());
byte [] modbus_bytes = {};
//read Modbus bytes from client to get client request
modbus_bytes = in.readAllBytes();
System.out.println("Modbus request: ");
for (byte b: modbus_bytes){
System.out.print(b);
}
System.out.println();
//transfer modbus request to modbus server
modbus_out.write(modbus_bytes, 0, modbus_bytes.length);
//get response from modbus server
modbus_bytes = modbus_in.readAllBytes();
System.out.println("Modbus response: ");
for (byte b: modbus_bytes){
System.out.print(b);
}
System.out.println();
//transfer response to client
out.write(modbus_bytes,0,modbus_bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
//close TCP connection
try {
in.close();
out.close();
clientSocket.close();
System.out.println("Connection terminated");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Connection termination failed");
}
}
}
Also find below, the wireshark screenshot
Call DataOutputStream.flush() after DataOutputStream.write() to force the bytes to be send
I managed to fix it. I mistakenly passed clientSocketinstead of modbusSocketas a parameter to the modbus_inand modbus_outStream instances. I also had to poll for availability of data before reading and then writing. Also, I noticed that the client-side closed the TCP session while the server-side had it open. So I ensured that the connection was closed after each query.
Please find modified code below for ClientHandler:
import java.io.*;
import java.net.Socket;
public class ClientHandler extends Thread {
private Socket clientSocket;
private Socket modbusSocket;
private DataOutputStream out, modbus_out;
private DataInputStream in, modbus_in;
public ClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
System.out.println(clientSocket.getInetAddress());
try {
out = new DataOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()));
in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
// in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// String readline;
//for connection to modbus server
modbusSocket = new Socket("127.0.0.1", 502);
// modbusSocket.setSoTimeout(10000);
modbus_out = new DataOutputStream(new BufferedOutputStream(modbusSocket.getOutputStream()));
modbus_in = new DataInputStream(new BufferedInputStream(modbusSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
//connection from client
if (in.available() > 0) {
//read Modbus bytes from client to get client request
System.out.println("===============Begin reading===============");
byte[] modbus_bytes = new byte[in.available()];
in.read(modbus_bytes);
System.out.println("Modbus request: ");
for (byte b : modbus_bytes) {
System.out.print(b);
}
System.out.println();
//transfer modbus request to modbus server
modbus_out.write(modbus_bytes);
modbus_out.flush();
System.out.println("Written to modbus server");
while (modbus_in.available() == 0) {
System.out.println("Waiting for device response...");
}
System.out.println("\nDevice response ready");
//get response from modbus server
modbus_bytes = new byte[modbus_in.available()];
modbus_in.read(modbus_bytes);
System.out.print("Modbus response: ");
for (byte b : modbus_bytes) {
System.out.print(b);
}
System.out.println("\nSending response to client");
//transfer response to client
out.write(modbus_bytes);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
//close TCP connection
try {
// in.close();
// out.close();
clientSocket.close();
modbusSocket.close();
System.out.println("===========Connection terminated==============");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Connection termination failed");
}
}
}
I am developing a proxy server based on java. For simple http request, proxy server is working. But for HTTPS Connection, connection gets timed out. Here are the steps I did. I first read one line from input stream and created a socket connecting Server. After that I gave 200 Status to client. After that I asynchronously read and write between Client Socket and Server socket. But currently this isn't working and connection gets timedout and I couldn't debug the problem.
public class ProxyServer extends Thread {
private String host;
private int port;
private ServerSocket serverSocket;
private InputStream proxyToClientIP;
private OutputStream proxyToClientOP;
private InputStream proxyToServerIP;
private OutputStream proxyToServerOP;
private Socket socket;
private Socket socketFromProxyServer;
ProxyServer(ServerSocket serverSocket, Socket socket) {
this.serverSocket = serverSocket;
this.socket = socket;
this.start();
}
public void run() {
processInputRequest();
}
public void processInputRequest() {
try {
proxyToClientIP = socket.getInputStream();
proxyToClientOP = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(proxyToClientIP));
String hostDetails = reader.readLine();
System.out.println(hostDetails);
boolean isConnect = false;
//Need to parse request and find req type as GET or CONNECT
//As of now we assume it to be Connect request
if (!isConnect) {
processGetRequest();
} else {
processConnectRequest();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void processConnectRequest() {
//Need to get host name from request. Currently Hardcoded for developing purpose
host = "harish-4072";
port = 8383;
try {
socketFromProxyServer = new Socket(host, port);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proxyToClientOP));
writer.write("HTTP/1.1 200 Connection established\r\n" + "\r\n");
writer.flush();
proxyToServerOP = socketFromProxyServer.getOutputStream();
proxyToServerIP = socketFromProxyServer.getInputStream();
proxyRequest();
} catch (IOException ex) {
System.out.println(ex);
}
}
public void proxyRequest() {
try {
new Thread() {
#Override
public void run() {
try {
byte[] read = new byte[1024];
int in;
System.out.println("Reading");
while ((in = proxyToClientIP.read(read)) != -1) {
proxyToServerOP.write(read, 0, in);
proxyToServerOP.flush();
}
} catch (SocketException e) {
System.out.println(e);
} catch (IOException ex) {
}
}
}.start();
byte[] reply = new byte[1024];
int out;
System.out.println("Writing");
while ((out = proxyToServerIP.read(reply)) != -1) {
proxyToClientOP.write(reply, 0, out);
proxyToClientOP.flush();
}
} catch (IOException ex) {
}
public void processGetRequest() {
//
}
}
I first read one line from input stream and created a socket connecting Server. ... After that I asynchronously read and write between Client Socket and Server socket.
The problem is that you are reading only a single line while you would need to read the full HTTP request header from the client, i.e. everything up to the end of the request header (\r\n\r\n).
Because you fail to do so the unread parts of the HTTP request are forwarded to the server. But the server is expecting the start of the TLS handshake and these data confuse the server. This might result in hanging or aborting, depending on the content of the data and one the kind of server.
I am trying to send a ByteBuffer array over a socket on the port 25565 on the address "localhost". But for some reason, Java is throwing a connection reset exception when doing input.read(). Could someone please tell me whats going on?
Sender:
private static Socket socket;
public static void main(String[] args) throws IOException {
socket = new Socket("localhost", 25565);
String Password = "1234";
ByteBuffer Buffer = ByteBuffer.allocate(1 + Password.getBytes().length);
Buffer.put((byte) 0x00);
Buffer.putShort((short) Password.getBytes().length);
Buffer.put(Password.getBytes());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
output.write(Buffer.array());
}
public static void sendBytes(byte[] myByteArray) throws IOException {
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
output.write("LOL".getBytes());
output.flush();
}
Receiver:
public static void main(String[] args) {
try {
ServerSocket ServerSocket = new ServerSocket(25565);
System.out.println("Waiting for connection...");
Socket socket = ServerSocket.accept();
DataInputStream Input = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
System.out.println(Input.read());
ServerSocket.close();
socket.close();
} catch (Exception e) {
if(e instanceof SocketTimeoutException) {
System.out.println("THE SOCKET TIMED OUT!");
}
else {
e.printStackTrace();
}
}
}
Stack trace:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at net.networking.Receiver.main(Receiver.java:17)
NOTE: Yes, I do know that just using input.read() will not get the whole ByteBuffer array I'm trying to send. But right now I just want to read the first byte and print it out to the console.
You're not closing the connection in the sender, so it gets reset when the process exits.
private static Socket socket;
public static void main(String[] args) throws IOException {
socket = new Socket("localhost", 25565);
String Password = "1234";
sendBytes(Password.getBytes());
output.close();
}
public static void sendBytes(byte[] myByteArray) throws IOException {
ByteBuffer Buffer = ByteBuffer.allocate(3 + myByteArray.length);
Buffer.put((byte) 0x00);
Buffer.putShort((short) myByteArray.length);
Buffer.put(myByteArray);
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
output.write(Buffer.array());
output.flush();
}
You're only reading one byte and then closing the connection. You need to read the entire transmission. If you close a socket with unread data still pending, the connection is reset. Also, if you want to handle exceptions separately, catch them separately. Don't use instanceof.
public static void main(String[] args) {
try {
ServerSocket ServerSocket = new ServerSocket(25565);
System.out.println("Waiting for connection...");
Socket socket = ServerSocket.accept();
DataInputStream Input = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
byte b = Input.readByte();
short dataLen = Input.readShort();
byte[] data = new byte[dataLen];
Input.readFully(data);
// use data as needed...
System.out.println("Data received");
Input.close();
ServerSocket.close();
} catch (SocketTimeoutException e) {
System.out.println("THE SOCKET TIMED OUT!");
} catch (Exception e) {
e.printStackTrace();
}
}
This is my code:
import java.io.*;
import java.net.*;
public class proxy {
public static void main(String[] args) throws IOException {
try {
String host = "gamea.clashofclans.com";
int remoteport = 9339;
ServerSocket ss = new ServerSocket(0);
int localport = ss.getLocalPort();
ss.setReuseAddress(true);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport
+ " on port " + localport);
// And start running the server
runServer(host, remoteport, localport,ss); // never returns
System.out.println("Started proxy!");
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on
* the specified local port. It never returns.
*/
public static void runServer(String host, int remoteport, int localport, ServerSocket ss)
throws IOException {
// Create a ServerSocket to listen for connections with
System.out.println("Connected to Client!");
final byte[] request = new byte[2048];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
System.out.println("Client Accepted!");
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
System.out.println("Client connected to server.");
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":"
+ remoteport + ":\n" + e + "\n");
out.flush();
client.close();
System.out.println("Client disconnected");
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
}
}
}
When I run it I get to the message "Connected to client" (line 40) but after that nothing is happening in the window. I don't get the "Client has connected to the server message" so I assume the problem is somewhere around there?
Why is this happening? Does anyone know a fix?
I'm very new to java so please don't be harsh on me.
Your "Connected to Client!" message is misleading. At that point, you are starting your server and clients will soon be able to connect, but no clients have connected yet. Your program is waiting for
client = ss.accept();
to return. ServerSocket.accept waits for a connection to be made across the port. You need another thread, program, or computer to connect to this port to begin hosting them as a client. Make sure that this other thread, program, or computer is properly configured to connect to your open port. You likely need to either set ServerSocket to use a fixed port, or to determine what port it has opened a socket on and tell your other program what port to use.
I am working on my first Java/Android sockets app that will act as a send/receive socket client. I have an existing app (server) that communicates using xml via sockets. This server can send out information to connected clients at any time so I must keep the socket open indefinitely once it has been created. The code below seems to be partially correct as I can send and receive direct responses however, I am unable to receive unsolicited messages?
public void Connect(String ip, int port)
{
try
{
InetAddress inetAddress = InetAddress.getByName(ip);
Socket socket = new Socket(inetAddress, port);
mConnected = true;
try
{
mOutputStream = socket.getOutputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
new Thread(new NetworkConnectHandler()).start();
while (socket.isConnected())
{
while ((bytesRead = inputStream.read(buffer)) != -1)
{
mReceivedPacket = null;
byteArrayOutputStream.write(buffer, 0, bytesRead);
mReceivedPacket = byteArrayOutputStream.toString("UTF-8");
if (mReceivedPacket.indexOf(STX) > -1 && mReceivedPacket.indexOf(ETX) > -1)
{
break;
}
}
byteArrayOutputStream.reset();
if (mReceivedPacket != null)
{
IncomingPacketHandler(XmlFromString(CleanIncomingPacket(mReceivedPacket)));
}
}
}
catch (Exception ex)
{
Log.e("Network Connect", "S: Error", ex);
}
}
catch (Exception ex)
{
Log.e("Network Connect", "C: Error", ex);
}
}
public class NetworkConnectHandler implements Runnable
{
#Override
public void run() {
ConnectHandler();
}
}
protected void ConnectHandler()
{
Log.e("ConnectHandler", "Connected");
SendDoc(CreateIDPacket());
}
SendDoc sends an initial message to the server on the same socket that is created in the Connect method. All sent messages will receive a response from the server. In this case, the message is sent and the response is received.