Synchronize server with client java sockets - java

Currently I am working on a server/client application which sends data using java with Runnable and threads. The problem is that the client is sending the data and when the server starts to read it the client has already finished and closed the connection which on the server side only a partially of the data is arrived, can they be setup to be synchronized?
this is the client:
private void ConnectionToServer(final String ipAddress, final int Port) {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
socket = new Socket(ipAddress, Port);
bos = new BufferedOutputStream(socket.getOutputStream());
dos = new DataOutputStream(socket.getOutputStream());
File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");
String data = f.getName()+f.length();
byte[] b = data.getBytes();
sendBytes(b, 0, b.length);
dos.flush();
bos.flush();
bis.close();
dos.close();
//clientProcessingPool.submit(new ServerTask(socket));
} catch (IOException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex); } finally {
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
if (len < 0) {
throw new IllegalArgumentException("Negative length not allowed");
}
if (start < 0 || start >= myByteArray.length) {
throw new IndexOutOfBoundsException("Out of bounds: " + start);
}
// Other checks if needed.
// May be better to save the streams in the support class;
// just like the socket variable.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(len);
if (len > 0) {
dos.write(myByteArray, start, len);
}
}
server code:
private void acceptConnection() {
try {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(8080);
while (true) {
socket = server.accept();
System.out.println("Got a client !");
bis = new BufferedInputStream(socket.getInputStream());
dis = new DataInputStream(socket.getInputStream());
String data = readBytes().toString();
System.out.println(data);
bos.close();
dis.close();
//clientProcessingPool.submit(new ClientTask(socket));
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
} catch (Exception io) {
io.printStackTrace();
}
}
public byte[] readBytes() throws IOException {
// Again, probably better to store these objects references in the support class
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
int len = dis.readInt();
byte[] data = new byte[len];
if (len > 0) {
dis.readFully(data);
}
return data;
}

You mixed up many things:
Variables start most of the time with a lowercase letter, e.g. int port, int ipAddress
Classes start with a uppercase letter, e.g. Client, Server
only open one Data*stream on a socket. new DataInputStream(socket.getInputStream()) or new BufferedInputStream(socket.getInputStream()), but not both
If you need both, chain them: new DataInputStream(new BufferedInputStream(socket.getInputStream()));
KISS (Keep it short & simple)
If you use a DataInputStream, then use the given functionality of sending objects and primitives, e.g. sendUTF(), sendInt(), sendShort(), and so on...
Name your vars right: servertask is a client thread? no
Move long anonymous classes to a new class
Don't use port 8080, this port is used for many other application and will cause problems
example code regarding your example an my advices:
Server
public class Server implements Runnable {
private void acceptConnection() {
Thread serverThread = new Thread(this);
serverThread.start();
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(8081);
while (true) {
Socket socket = server.accept();
System.out.println("Got a client !");
// either open the datainputstream directly
DataInputStream dis = new DataInputStream(socket.getInputStream());
// or chain them, but do not open two different streams:
// DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
// Your DataStream allows you to read/write objects, use it!
String data = dis.readUTF();
System.out.println(data);
dis.close();
// in case you have a bufferedInputStream inside of Datainputstream:
// you do not have to close the bufferedstream
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new Server().acceptConnection();
}
}
description:
main: create a new Server Object, which is a Runnable
acceptConnections: create a Thread
run:
open a Serversocket
wait for a connection
open exactly one stream
read the Data
close the stream and wait for next connection
Client
public class Client {
private static void sendToServer(String ipAddress, int port) throws UnknownHostException, IOException {
Socket socket = new Socket(ipAddress, port);
// same here, only open one stream
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");
String data = f.getName()+f.length();
dos.writeUTF(data);
dos.flush();
dos.close();
}
public static void main(String[] args) throws UnknownHostException, IOException {
Client.sendToServer("localhost", 8081);
}
}
description (This one is straight forward):
open socket
open DataStream
send Data
flush and close

Related

How to send and receive file with socket programming in java

Hello I have a problem with sending and receiving files through sockets in java
I've written 2 while in client and session class one for sending and one for receiving
program starts and send a request file from client to session then session receives it and creates it
after that session send response file to client and client receives it and creates it
when I remove 2nd "while"s in both client and session class , program works and client sends data and session receives it and create the file
but when I add 2nd "while"s again , program stuck and even last operation that I mentioned won't work
Server Class
public class Server {
public Server(int port) {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
Socket client = server.accept();
System.out.println("New client connected" + client.getInetAddress().getHostAddress());
Session clientSocket = new Session(client);
new Thread(clientSocket).start();
}
} catch (IOException i) {
System.out.println(i);
}
}
public static void main(String args[]) {
Server server = new Server(5000);
}}
Session Class :
public class Session implements Runnable{
private Socket socket;
public Session(Socket socket){
this.socket = socket;
}
public void run(){
try {
FileOutputStream fileOutputStream = new FileOutputStream("RequestClient.txt");
FileInputStream fileInputStream = new FileInputStream("Response.txt");
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
int count;
byte[] bytes = new byte[4096];
while ((count = dataInputStream.read(bytes)) > 0) {
fileOutputStream.write(bytes, 0, count);
}
while ((count = fileInputStream.read(bytes)) > 0) {
dataOutputStream.write(bytes, 0, count);
}
fileInputStream.close();
fileOutputStream.close();
dataOutputStream.close();
dataInputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}}
Client Class :
public class Client {
public Client (String address, int port) {
Socket socket = null;
try {
socket = new Socket(address, port);
File requestFile = new File("Request.txt");
FileOutputStream fileOutputStream = new FileOutputStream("ResponseServer.txt");
FileInputStream fileInputStream = new FileInputStream(requestFile);
DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
int count;
byte[] buffer = new byte[4096];
while ((count = fileInputStream.read(buffer)) > 0) {
dataOutputStream.write(buffer, 0, count);
}
while ((count = dataInputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, count);
}
fileInputStream.close();
fileOutputStream.close();
dataOutputStream.close();
dataInputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Client connectionService = new Client("127.0.0.1", 5000);
}}

Sending Strings through Sockets

Here is the Server
public class SocketMsg {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket("number goes here");
System.out.println("Server Ready");
ss.accept();
}
}
Client:
public class SocketMesg {
public static void main(String[] args) throws IOException{
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("localhost", "number goes here");
osw =new OutputStreamWriter(socket.getOutputStream());
osw.write(str, 0, str.length());
} catch (IOException e) {
System.err.print(e);
}
finally {
socket.close();
}
}
Personally, the code works but the strings are not sending to the other host, I gave them the same number, but it is not working. The client is sending it back to the server on the DOS window. Did I make a error? What did I do wrong?
Your server-side at least needs the following.
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
// process inputLine;
}
You need to flush outputstream to commit write buffer to the socket. Also be careful with charset if writing strings. This example explicitly uses UTF-8 through "low level" byte array buffer. I think you are practicing your first socket programming so I kept this very simple.
Server.java
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(1122);
System.out.println("Server Ready");
while(true) {
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
// client must send 1-10 bytes, no more in single command
byte[] buf = new byte[10];
int read = is.read(buf, 0, buf.length);
String cmd = new String(buf, 0, read, "UTF-8");
System.out.println(cmd);
socket.close(); // we are done, this example reads input and then closes socket
}
}
}
Client.java
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = null;
// send max of 10 bytes to simplify this example
String str = "ABCDEFGHIJ";
try {
socket = new Socket("localhost", 1122);
OutputStream os = socket.getOutputStream();
byte[] buf = str.getBytes("UTF-8");
os.write(buf, 0, buf.length);
os.flush();
} catch (IOException ex) {
System.err.print(ex);
} finally {
socket.close();
}
}
}

Null pointer exception occurs while trying to read repeatedly from an InputStream

The code works fine when I close the client just after sending one instruction. But when I want a client and server connection to persist, so that the client can send multiple instructions to the server one after another, I get a Null pointer exception at the server and the message java.net.SocketException: Socket is closed at the client. This happens after the client sends a file to the server and the server successfully receives it. Need help. The error occurs at the Connection class code line switch(clientMsg). It seems to me that for some reason the BufferedReader in goes null, but I might be mistaken about that. The code is as follows. Thanks.
Server
public class server {
private static ServerSocket serverSocket;
private static Socket socket = null;
public static void print(Object s) {
System.out.println(s);
}
#SuppressWarnings("resource")
public static void main (String args[]) throws IOException {
System.out.print("Specify listening port: ");
Scanner _a = new Scanner(System.in);
int a = _a.nextInt();
try{
serverSocket = new ServerSocket(a);
}
catch(IOException e) {
System.out.println(e);
}
while (true) {
try {
socket = serverSocket.accept();
print("Connected to " + socket);
Thread client = new Thread(new Connection(socket));
client.start();
}
catch (IOException e) {
print(e);
}
}
}
}
Connection
public class Connection implements Runnable {
public static void print(Object s) {
System.out.println(s);
}
private Socket socket;
private BufferedReader in = null;
public Connection(Socket client) {
this.socket = client;
}
#Override
public void run(){
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String clientMsg;
while (true) {
clientMsg = in.readLine();
switch (clientMsg) {
case "1":
receiveFile(); //method code not included
break;
default:
print("Command not recognized");
break;
}
//in.close();
}
}//try run()
catch (IOException e) {
print(e);
}
}
Client
public class client {
private static Socket connectToServer;
private static String fileName;
private static BufferedReader keybrdIn;
private static PrintStream msgToServer;
public static void println(Object e) {
System.out.println(e);
}
public static void print(Object e) {
System.out.print(e);
}
public static void main(String args[]) throws IOException{
try{
print("Enter IP: ");
String ip = new Scanner(System.in).nextLine();
print("Enter port: ");
int port = new Scanner(System.in).nextInt();
connectToServer = new Socket(ip, port);
keybrdIn = new BufferedReader(new InputStreamReader(System.in));
}catch(IOException e) {
println(e);
}
msgToServer = new PrintStream(connectToServer.getOutputStream());
while (true) {
try {
switch(Integer.parseInt(action())) { //action() method code not included
case 1:
msgToServer.println("1");
sendFile();
break;
default:
println("Invalid input");
break;
}
}catch (IOException e) {
println(e);
}
}
}
sendFile()
public static void sendFile() throws IOException {
print("Enter file name: ");
fileName = keybrdIn.readLine();
File file = new File(fileName);
byte[] bytearray = new byte[8192];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = connectToServer.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
int count;
while ((count = dis.read(bytearray)) > 0){
dos.write(bytearray, 0, count);
}
dis.close();
dos.flush();
dos.close();
}
receiveFile()
public void receiveFile() {
try {
int count;
DataInputStream clientFileStream = new DataInputStream(socket.getInputStream());
String fileName = clientFileStream.readUTF();
OutputStream fileOutput = new FileOutputStream("_" + fileName);
byte[] mybytearray = new byte[8192];
BufferedOutputStream bos = new BufferedOutputStream(fileOutput);
System.out.println("Downloading " + fileName + " ...");
//outToClient().writeBytes("Uploading. Please wait...\n");
while ((count = clientFileStream.read(mybytearray)) > 0){
bos.write(mybytearray, 0, count);
}
fileOutput.close();
bos.close();
clientFileStream.close();
}
catch (IOException e) {
print(e);
}
}
In sendFile(), you close the data output stream which closes your underlying connection's output stream.
According to the documentation of Socket.getOutputStream():
"Closing the returned OutputStream will close the associated socket".
Since you already closed stream, it will also close socket as well as Eyal mentioned. However, at the moment you close the stream, server side will aware of that and return -1 for read() results.
So, even if you didn't specify file length at beginning, this will generally works well.
However, since you already closed stream, you can't reuse it no matter what. To fix this issue, probably you need to change your Client class so that Client should create socket connection, send files, close socket. That's one lifecycle of opened client socket.
Or maybe in while loop of Client class, 1) take ip, port, and filename to send 2) Create new Thread and provide those information so let thread open connection, send file, close connection 3) and in the meantime, client while() can keep take next ip, port, and filename to send from the user. By doing this, you don't need to make client program wait until file transfer to be completed.
Regarding the NPE in the server, readLine() returns null at end of stream. You are ignoring it. You should be testing for it immediately after the call, and if null close the socket and exit the read loop.

Issue with proxy done with sockets

I have a problem with this piece of code but I'm not able to see where is the error.
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class Server {
public void startServer() {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
#SuppressWarnings("resource")
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
private class ClientTask implements Runnable {
private Socket clientSocket;
private ClientTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
// Read request
InputStream incommingIS = clientSocket.getInputStream();
byte[] b = new byte[8196];
int len = incommingIS.read(b);
if (len > 0) {
System.out.println("REQUEST"
+ System.getProperty("line.separator") + "-------");
System.out.println(new String(b, 0, len));
// Write request
Socket socket = new Socket("localhost", 8080);
OutputStream outgoingOS = socket.getOutputStream();
outgoingOS.write(b, 0, len);
// Copy response
OutputStream incommingOS = clientSocket.getOutputStream();
InputStream outgoingIS = socket.getInputStream();
for (int length; (length = outgoingIS.read(b)) != -1;) {
incommingOS.write(b, 0, length);
}
incommingOS.close();
outgoingIS.close();
outgoingOS.close();
incommingIS.close();
socket.close();
} else {
incommingIS.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
This code tries to simulate a HTTP proxy using sockets, the code receives the URL, process it and get back again to the browser untouched.
The problem is that the browser hangs, nothing is returned...
Any help would be much appreciated.
This is not a correct way to write a proxy. An HTTP proxy receives a CONNECT command, which tells it to connect to an upstream target. So the first thing you have to do is read one line, do the upstream connect, and return an appropriate status. If the status was OK, you then have to start two threads to copy bytes between upstream and downstream, one in each direction, closing both sockets when you have received EOS from both of them.

Implementation of a simple file transfer client server

Hi I have the following code to the client - server through the thread, I have a errors,
Can't setup server on this port number.
Can't setup server on this port number.
but why?
class client:
import java.io.*;
import java.net.Socket;
// create class client
public class Client extends Thread {
Socket socket = null;
Socket socket1 = null;
// create send method
public void sendFile() throws IOException {
String host = "127.0.0.1";
String host1 = "127.0.0.2";
socket = new Socket(host, 4444);
socket1 = new Socket(host1, 444);
File file = new File("/home/reza/Desktop/link help");
File file1 = new File("/home/reza/Desktop/hi");
long length = file.length();
long length1 = file1.length();
byte[] bytes = new byte[(int) length];
byte[] bytes1 = new byte[(int) length1];
FileInputStream fis = new FileInputStream(file);
FileInputStream fis1 = new FileInputStream(file1);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
BufferedInputStream bis1 = new BufferedInputStream(fis1);
BufferedOutputStream out1 = new BufferedOutputStream(socket1.getOutputStream());
int count;
int count1;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
while ((count1 = bis1.read(bytes1)) > 0) {
out1.write(bytes1, 0, count1);
}
Thread t = new Thread(new Runnable() {
public void run()
{
while(socket.isConnected())
{
Wait2();
try {
sendFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread t1 = new Thread(new Runnable() {
public void run() {
while(socket1.isConnected())
{
Wait2();
try {
sendFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t.start();
t1.start();
fis.close();
fis1.close();
out.close();
bis.close();
out1.close();
bis1.close();
socket.close();
socket1.close();
}
public void Wait2()
{
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
}
// class server
import java.io.*;
import java.net.*;
public class Server {
public void recivefile() throws IOException {
ServerSocket serverSocket = null;
ServerSocket serverSocket1 = null;
try {
serverSocket = new ServerSocket(4444);
//serverSocket1 = new ServerSocket(444);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
try {
serverSocket1 = new ServerSocket(444);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
Socket socket = null;
Socket socket1 = null;
InputStream is = null;
InputStream is1 = null;
FileOutputStream fos = null;
FileOutputStream fos1 = null;
BufferedOutputStream bos = null;
BufferedOutputStream bos1 = null;
int bufferSize = 0;
int bufferSize1 = 0;
try {
socket = serverSocket.accept();
socket1 = serverSocket1.accept();
} catch (IOException ex) {
System.out.println("Can't accept client connection. ");
}
try {
is = socket.getInputStream();
is1 = socket1.getInputStream();
bufferSize = socket.getReceiveBufferSize();
bufferSize1 = socket1.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
System.out.println("file recieved");
System.out.println("Buffer size1: " + bufferSize1);
System.out.println("file recieved");
System.out.println("file recieved");
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream("/home/reza/Desktop/reza");
bos = new BufferedOutputStream(fos);
fos1 = new FileOutputStream("/home/reza/Desktop/ali");
bos1 = new BufferedOutputStream(fos1);
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
}
public static void main(String[] args) throws IOException
{
System.out.println("server is run, please send file");
Server s = new Server();
s.recivefile();
}
}
error is :
Can't setup server on this port number.
Can't setup server on this port number.
You can't start a server on 127.0.0.2 - therein lies your problem.
netstat -ano | find "1024"
try above command if you are running your java files on windows environment that will help you to find any process using same port no as yours and also use
ex.printStackTrace() along with
System.out.println("Can't setup server on this port number.");
Assuming that your code runs on a unix platform, your server code is trying twice to open a socket on port 444, which is a system reserved port. In order to be able to succeed, your programme must run with administrative priviledges, and you must ensure that the port is not already used by another process.
A possible workaround is to:
use a port above 1024. These ports are free to use for userland programmes
in case of failure have a backup port, also above 1024. You must amend both server and client codes to try both ports, and of course your communication protocol must include some form of handshaking to make sure they are talking to the right interlocutor.
There are many other problems with your code listed in other answers.
you don't need to make every objects twice. Only one instance is enough in most cases,
if your server is running continuously and must accept many connections, you should not close the accepting socket at the end of one receiving session.
also the server is supposed to run a loop on the server socket accept call, and start a new thread for each incoming connection, whose job is to handle that connection.
While I understand your willingness to learn and experiment, there are existing solutions to what you are trying to achieve. For instance, you could simply use a FTP server for your purpose.
The way you have written client - server program is wrong I guess.
Following are the mistakes you have done...
1) In Client class, you have sendFile function in which you've created two threads - t & t1. In run function you are again calling the same sendFile function.
So it keeps creating threads under threads just like recursion.
2) In Server class, you are listening to two port within the same recieveFile function. As the socket = serverSocket.accept() is a blocking call, It wont excecute the rest of the code untill it finds a single client to connect.
So what exactly happens here is.. Once the first client connects, thenafter immediately it expects second client to connect.
In the mean time your client thread may try to access the port on which connection has not been established.
In short, your SERVER SHOULD BE IN A THREADING ENVIRONMENT NOT THE CLIENT.
And I would suggest that for different port you should use different server.
i.e. create different server class for both 1024 & 1025 port.

Categories