Fill ArrayList with sockets in constructor? - java

I am currently trying to take an ArrayList and fill it with sockets using .add, when the socket is passed into the constructor. When i run the debug, it looks like there is only ever 1 socket filling the ArrayList, and no more, even though I've opened like 6 client threads.
Server class
public static void main(String[] args) throws IOException
{
final int PORT = 8888;
ServerSocket server = new ServerSocket(PORT);
System.out.println("Waiting...");
while(true)
{
Socket s = server.accept();
System.out.println("Client connected");
Service service = new Service(s);
Thread t = new Thread(service);
t.start();
}
Service class
public class Service implements Runnable
{
private Socket s;
private Scanner in;
private PrintWriter out;
private ArrayList<Socket> sockets = new ArrayList<Socket>();
public Service(Socket aSocket)
{
s = aSocket;
sockets.add(s);
}

It's because you create a new Service every loop => you will have 6 Service objects with one arrayList in each containing each objects socket. If you want your arrayList to contain all clients / sockets, you will have to have this list in your server class. Also it's rarely a good idea for your clients to know about all other clients.
I also suggest putting in a Thread.sleep(100) in your main method (server), otherwise it will take up a lot of your precessing power.
public static void main(String[] args) throws IOException
{
final int PORT = 8888;
ServerSocket server = new ServerSocket(PORT);
System.out.println("Waiting...");
private ArrayList<Socket> sockets = new ArrayList<Socket>();
while(true)
{
Thread.sleep(100);
Socket s = server.accept();
System.out.println("Client connected");
Service service = new Service(s);
Thread t = new Thread(service);
t.start();
sockets.add(s);
}

Related

does not read anything using ObjectInputStream in Java socket

I created a simple server and a client, but the server could not read anything that was sent from the client. I also add a print statement after I sent the string, but it cannot be printed either.
public class Server {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket clientSocket = serverSocket.accept();
System.out.println("accepting client at address " + clientSocket.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
String input = (String) in.readObject();
System.out.println(input);
out.writeObject("Received");
out.flush();
}
}
Below is the client, and I just want to send a string "?????does not send":
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Client client = new Client();
client.sentInfo();
}
private static class Client {
private ObjectInputStream objectInputStream;
private ObjectOutputStream objectOutputStream;
public Client() throws IOException {
Socket socket = new Socket("127.0.0.1", 6666);
this.objectInputStream = new ObjectInputStream(socket.getInputStream());
this.objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
}
public void sentInfo() throws IOException, ClassNotFoundException {
this.objectOutputStream.writeObject("?????does not send");
this.objectOutputStream.flush();
System.out.println("????????");
Message resp = (Message) this.objectInputStream.readObject();
System.out.println(resp.getMessage());
}
}
}
I tried something else, if I just use InputStream and use a buffer to read bytes, like this:
Server code
This is the client code: client code
The code in the two link above would work. However, it would not work if I tried to use ObjectInputStream:
This is the server: server
This is the client: client
This is the Message object I want to send: Message class
Can someone explain this for me please? Thanks!
To read Strings from a socket use something like this:
DataInputStream input = new DataInputStream(clientSocket.getInputStream());
String message = input.readUTF();
You can open multiple streams from a socket, so if you want to read something else that really needs the ObjectInputStream than it can be open as well. Don't forget to properly close the streams & sockets.

Simple Java multi-threaded socket application

I have this simple multi-threaded java socket application. Using classes Client.java
public class Client {
private static Socket socket;
private static boolean waitForServer = false;
public static void main(String[] args) throws IOException {
while(true){
socket = new Socket("localhost", ServerPortInfo.getPort());
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
BufferedReader bufferedReader = new java.io.BufferedReader(new InputStreamReader(System.in));
while(true){
PrintWriter.println(name + " Hello");
waitForServer = true;
if (waitForServer){
BufferedReader inputBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputString = null;
while((inputString = inputBufferedReader.readLine()) != null){
System.out.println(inputString);
break;
}
}
}
}
}
}
And Server.java
public class Server {
public static ArrayList<ServerThread> connections = new ArrayList<ServerThread>();
public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
// Init server functionality
new Server().runServer();
}
// Implementing server functionality
public void runServer() throws IOException{
ServerSocket serverSocket = new ServerSocket(ServerPortInfo.getPort());
System.out.println("Server is running... Waiting for connections");
while (true){
Socket socket = serverSocket.accept();
// After connection handle clients in threads
ServerThread newThread = new ServerThread(socket);
connections.add(newThread);
newThread.start();
}
}
}
And then a Thread that handles that connection...
public class ServerThread extends Thread {
private static Socket socket;
public static boolean alive = true;
ServerThread(Socket socket){
this.socket = socket;
}
public void run(){
if (alive) {
//DO STUFF NOW
}
}
And now when I have multiple connections. It creates a different Thread for every connection.
What should i do when a user wants to disconnect from this server?
Should i kill the thread, socket?
I tried just saying to the thread
alive = false; so the run would just stop running. But this breaks other connections as well.
EDIT
ServerThread ->
private Socket socket;
And a function ->
void closeConnection() throws IOException{
this.socket.close();
}
works like a charm.
public static variables are a recipe for disaster (as I'm sure you've
just found out the hard way). But as #cktang said, close the socket,
then kill that thread (not the others). -#JoeC
Changed private static Socket socket; to private Socket socket;.
Closed the socket and then Thread.
The problem is with
public static boolean alive = true;
private static Socket socket;
As it is static, it influences all your ServerThread's, but each ServerThread (aka connected client) should have its own socket and flag indicating if it's alive or not.
Remove the static modifier from both attributes and
make the flag private volatile boolean alive = true;
At first close the socket a then stop the thread (and remove it from the list).

Java Multi Client server socket

I am trying to establish a communication between a server (NewServer class) and a client (NewClient class), accepting two Client communications. I know how to do it with one client but not multiple client connections.
Do I have to create 2 readers in the Client class?
Can I do this in a recursive way?
Server Class:
import java.net.*;
import java.io.*;
public class NewServer
{
//Create Server Socket and a Client Socket for each Client.
static ServerSocket server;
static Socket client1;
static Socket client2;
//Create OutputStreams to send information to each Client.
static DataOutputStream client1writer;
static DataOutputStream client2writer;
static final int PORT = 9999;
//Main Method
public static void main(String[]args)
{
//Try-Catch Block for Socket Errors.
try
{
//Create the Server Socket as a Host.
server = new ServerSocket(PORT);
//Connect Client 1 – First run of the Client class.
client1 = server.accept();
client1writer = new
DataOutputStream(client1.getOutputStream());
//Connect Client 2 – Second run of the Client class.
client2 = server.accept();
client2writer = new
DataOutputStream(client2.getOutputStream());
//Assign each Client an ID number – this is how the Client will know
// which individual Client it’s representing in RunTime.
int ID1 = 8675309;
int ID2 = 8675308;
//Tell both Clients which one they are representing.
client1writer.writeInt(ID1);
client2writer.writeInt(ID2);
//Close all Sockets when finished.
client1.close();
client2.close();
server.close();
}
catch (IOException IOex)
{
System.out.println("Server Error.");
}
}
}
Client class:
import java.net.*;
import java.io.*;
public class NewClient {
static Socket client = null;
static final int PORT = 9999;
static final String IP = "localhost";
public static void main(String[] args) throws IOException {
int id1;
int id2;
try{
client = new Socket(IP,PORT);
System.out.println("Connection successful!");
reader = new DataInputStream(client.getInputStream());
id1 = reader.readInt();
id2 = reader.readInt();
System.out.println("The id of the user is " + id);
//Closing everything
client.close();
reader.close();
}catch(IOException error) {
System.err.println("Server error.");
}
}
}
You can achieve it by starting a separate thread (also known as Plain threads for every new client connection and then call server.accept() which runs in a loop. It is useful as an learning example but will not help you achieve what you need as you loose control of threads.
Second way is to use Executor Service which provides better management control over the above solution.

Single Threaded Server Implementation to Multi Threaded

Guys I want to convert my server implementation into multi thread so that it can handle multiple requests. Basically the server is connected with an android application and it is recieving an image from android application. I want to add a thread so that it can handle multiple requests and the thread should start when the request is recieved. Kindly help me out.
This is the Server Code.
public static void main(String[] args) throws UnknownHostException, IOException, MatlabInvocationException, MatlabConnectionException {
while (true) {
try {
serverSocket = new ServerSocket(4001); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4001");
}
System.out.println("Server started. Listening to the port 4001");
clientSocket = serverSocket.accept();
DataInputStream inputFromClient = new DataInputStream(clientSocket.getInputStream());
int count = inputFromClient.readInt();
int available = inputFromClient.available();
System.out.println("Length of Image in Bytes:" + count);
System.out.println("available:" + available);
image = new byte[count];
inputFromClient.readFully(image);
System.out.println(image.length);
System.out.println(image);
final BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(image));
ImageIO.write(bufferedImage, "jpg", new File("image.jpg"));
System.out.println("Image has been wriiten in the directory.");
MatlabProxyFactory mpf = new MatlabProxyFactory();
MatlabProxy proxy = mpf.getProxy();
proxy.eval("conclusion=DetectColorL");
Object[] obj = proxy.returningEval("conclusion", 1);
String Message = obj[0].toString();
DataOutputStream outTo = new DataOutputStream(clientSocket.getOutputStream());
outTo.writeUTF(Message.toString());
System.out.println(Message);
proxy.disconnect();
serverSocket.close();
To make it multithreaded you want to be able to have multiple clients connected at the same time, to handle multiple requests instead of one at a time.
To do so, your server will have to permanently accept new clients.
public static void main(String[] args) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(4001); // Server socket
System.out.println("Server started. Listening to the port 4001");
while (true) {
// Always accept new clients
Socket clientSocket = serverSocket.accept();
new RequestHandlingClass(clientSocket).start(); // Make a new thread and call it's run procedure
}
} catch (IOException e) {
System.out.println("Could not listen on port: 4001");
}
}
Now our server accepts multiple clients we have to implement the RequestHandlingClass class. You want that class to listen for client requests and handle them.
public class RequestHandlingClass() extends Thread {
Socket clientSocket;
DataInputStream inputFromClient;
RequestHandlingClass(Socket clientSocket) {
this.clientSocket = clientSocket;
this.inputFromClient = new DataInputStream(clientSocket.getInputStream());
// ...
}
public void run() {
// Handle client requests
}
}
Based on your question I suppose you want to execute the "image handling" code in the run method.

Creating a socket server which allows multiple connections via threads and Java

I am trying to adapt my simple socket server so that it can have multiple TCP connections, via multithreading, but I can't seem to get it to work. My code so far is as follows, I'm not really sure where to go from here :
import java.net.*;
import java.io.*;
public class DoSomethingWithInput implements Runnable {
private final Socket clientSocket; //initialize in const'r
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String nextline;
while ((nextline = in.readLine())!=null) {
System.out.println(nextline);
} //... close socket, etc.
}
}
public class Socket{
public Socket() {
}
#Override
public void run() {
try {
ServerSocket serverSocket = null;
serverSocket = new ServerSocket(5432);
for (;;) {
ServerSocket serverSocket = null;
serverSocket = new ServerSocket(5432);
for (;;) {
Socket clientSocket = null;
clientSocket = serverSocket.accept();
//delegate to new thread
new Thread(new DoSomethingWithInput(clientSocket)).start();
}
}
}catch (IOException e) {
System.err.println("Could not listen on port: 5432.");
System.exit(1);
}
}
}
Would anyone be able to give me some pointers on how I could do this, and why my current implementation will not work ? I was running through the tips in the Java tutorial http://download.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServerThread.java here, but the example they give here seems to use a lot of outside sources and classes like KnockKnockProtocol etc etc.
Would anyone be able to help me out with this?
Thank you very much!
The problem is that currently you're accepting the connection, but then immediately performing blocking reads on it until it's closed:
// After a few changes...
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String nextLine;
while ((nextLine = in.readLine()) != null) {
System.out.println(nextline);
}
That means the same thread which accepts the connection is trying to handle the connection. That won't let you use multiple connections at the same time.
Instead, create a class (e.g. ConnectionHandler) which implements Runnable, and has a constructor taking a Socket. Its run method should handle the connection. Then change your code to:
Socket clientSocket = serverSocket.accept();
Runnable connectionHandler = new ConnectionHandler(clientSocket);
new Thread(connectionHandler).start();
That will leave your "main" thread free to wait for the next connection.
(By the way, the KnockKnockProtocol class isn't really "external" - it's part of the example. They just didn't make it very clear that the source is here...)
You're not multithreading. You're creating a thread which binds on a port and then reads from any client socket until the connection is closed.
You need to pass the socket to a new thread and have it read.
public class DoSomethingWithInput implements Runnable {
private final Socket clientSocket; //initialize in const'r
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String nextline;
while ((nextline = in.readLine())!=null) {
System.out.println(nextline);
} //... close socket, etc.
}
}
//...
ServerSocket serverSocket = null;
serverSocket = new ServerSocket(5432);
for (;;) {
Socket clientSocket = null;
clientSocket = serverSocket.accept();
//delegate to new thread
new Thread(new DoSomethingWithInput(clientSocket)).start();
} //...

Categories