I'm using a server socket to accept clients on the main thread, when a thread is accepted,the clients socket is given to a handler which is started in a new thread to process communications. However, before I start running my server to access clients, it connects to a second server which it must list to and be able to respond to and pass on the messages it gets to it's clients.
Hopefully this image illustrate what I mean:
The small server must be continuously listening for input from the big server, and also able to output responses.
//Default constructor
private smallServer(){}
//method to initialise and start the server
public static void StartServer(int port) throws IOException {
smallServer ss = new smallServer();
ss.bs= new bigServerClient(ss);
Thread nsc_Thread = new Thread(ss.bsc);
bsc_Thread.start();
//accepts clients and starts new thread for them
ss.ServerRun(port);
}
private void ServerRun(int port) throws IOException {
ServerSocket server = new ServerSocket(port);
server.setSoTimeout(50);
while (run) {
Socket client = null;
try {
client = server.accept();
} catch (SocketTimeoutException e) {
}
if (client != null) {
ClientHandler handler = new ClientHandler(client, this);
Thread handleThread = new Thread(handler);
handleThread.start();
}
}
if (!run) {
synchronized (ClientHandler.handlers) {
for (ClientHandler handler : ClientHandler.handlers) {
handler.terminateHandler();
}
}
System.exit(0);
}
}
public void processBigServerCommand(String toProcess) {
System.out.println("RESEAVED: " + toProcess);
}
The big server client(on the small server) then does this:
public class bigServerClient implements Runnable {
private smalsServer ss;
private PrintWriter printer;
private BufferedReader reader;
private Socket socket;
public bigServerClient(smallServer _ss) throws IOException {
ss = _ss;
socket = new Socket("Localhost", 5000);
printer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printer.flush();
SendBigServerMessage("Starting String");
}
private void SendBigServerMessage(String toSend) {
printer.print(toSend);
printer.flush();
}
#Override
public void run() {
try {
while (ss.state()) {
String inputLine;
while ((inputLine = reader.readLine()) != null) {
ss.processBigServerCommand(inputLine);
System.out.println(inputLine);
}
}
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException ex) {
}
}
}
}
From what's above, can anyone see why the big server client isn't responding to the big server when a message is sent? I'm guessing it's something to do with the main thread blocking the second thread, but I'm not sure... Any help would be greatly appreciated.
You lost me in your code...
Simplify it.
Your smallServer (see class names conventions) should have persistent connection to BigServer (effectively it is BigServer client) - you can implement it in your smallServer class, it should connect (once) and open I/O to BigServer (once) and close everything once the connection is terminated.
As your smallServer will handle multiple clients and pass their requests to BigServer there is no guarantee of the order of BigServer responses - you should do something to handle that (maybe pass UUID with requests?)
Simplify your smallServer and make sure that it runs...
Related
hey I'm writing a simple code with a server socket and multiple clients which the server gets every client's username and stores them in a hashmap.the server accepts a socket client and the client enters the username but again the server accept the same socket client and it wants its username and the code stops here.i want it to work for multiple clients not just one.
server class:
public class Server implements Serializable{
// [..]
public void serverConnect() throws IOException, ClassNotFoundException
{
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true)
{
System.out.println("Waiting ...");
socket=listener.accept();
for (Socket socket:socketList.keySet())
{
if (this.socket==socket)
{
checkSocket=false;
}
}
if (checkSocket)
{
socketList.put(socket,socketNumber);
System.out.println("Client is connected");
inputReader = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(inputReader);
user = reader.readLine();
Server.userList.add(user);
socketNumber++;
}
checkSocket=true;
}
}
}
client class:
public class Client {
public Client() {
}
public void clientConnect() throws UnknownHostException, IOException {
System.out.println("enter your username");
Scanner scanner = new Scanner(System.in);
String msg = scanner.nextLine();
Socket socket = new Socket("localhost", 9090);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println(msg);
}
}
In principle you have the workings of single thread server (which means it can accept only one client connection at a time). The main issue is that you have over-complicated how you receive a connection.
You can simplify your current code by dealing by moving the client connection socket and readers into the local scope and dealing with the socket directly.
public void serverConnect() throws IOException {
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} catch (IOException ignore) {
} finally {
socket.close();
}
}
}
As you can see you don't need to keep hold of the socket beyond reading the value sent. If you are only expecting the one line of data from the client, you should also close the socket otherwise the client can hold the server hostage by not sending any data until the socket timeout is reached.
Further to this you also want to wrap the code inside the while loop with a try/catch block to prevent an exception terminating the server.
As I mentioned in the opening paragraph this code works as a single threaded server and it can only respond to a single request at a time. If you want to accept and process multiple requests you will need to spawn a new thread to handle the response. I would recommend constructing your code as below but for the sake of brevity you could do something like below:
public void serverConnect() throws IOException {
int MAX_WORKERS = 100;
ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
ServerSocket listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
service.submit(() -> {
System.out.println("Client is connected");
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} finally {
socket.close();
}
} catch (Throwable ignore) {
}
});
}
}
So all that is happening above is that we are creating a thread pool of 100 threads using the ExecutorService. This means in theory we can accept 100 concurrent connections.
When a connection is accepted, we submit the socket and worker code to a thread which means that the main thread can return to listening for a new connections.
I have a server whose port 80 is for occupied by HTTP transactions. I wanted to see the traffic in that port and I tried to use a socket program to listen to that port.
public Server(int serverPort) throws IOException {
super(serverPort);
try {
while (true) {
Socket socket = accept();
new ServerThread(socket);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
close();
}
}
// inner-class ServerThread
class ServerThread extends Thread {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
// Ready to conversation
public ServerThread(Socket s) throws IOException {
this.socket = s;
in = new BufferedReader(new InputStreamReader(socket
.getInputStream(), "UTF-8"));
out = new PrintWriter(socket.getOutputStream(), true);
start();
}
// Execute conversation
public void run() {
try {
// Communicate with client until "bye " received.
while (true) {
String line = in.readLine();
if (line == null || "".equals(line.trim())) {
break;
}
System.out.println("Received message: " + line);
out.println(line);
out.flush();
}
out.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new Server(80);
}
However, when I run that java application, it showed a BindException: Address already in use.
So what should I do to my code and make it listen to port 80, or are there any other ways to listen to that port in Java?
If I understand you correctly you are trying to sniff the packets that are being passed to your server. If that is the case there are some answers in this post.
What Server are you running it on?
it all depends on the type of server you're working on. Tomcat for example has the type of port it's running off of in the Server.xml file.
In Windows you can run your program by administrator. In Linux using root user.
(Disclaimer that some of this code will be similar to online tutorials)
I think I've made it so that my server can handle multiple requests at once using threads, but I'm not entirely sure. And on top of that I don't know how I would actually send multiple requests at once.
My goal is to run my client code multiple times in parallel to see what happens if multiple clients connect to the server at the same time.
Client code (in separate project package):
Client clientSocket = new Client(9990,"localhost");
Socket socket = new Socket(clientSocket.host,clientSocket.portNumber);
clientSocket.performTask(socket);
("performTask(socket)" sends data to the server to perform a task)
Server code (separate project package from client code):
Server server = new Server(9990);
int clientNumber = 0;
ServerSocket socket = new ServerSocket(server.portNumber);
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).go();
clientNumber++;
}
}
finally {
socket.close();
}
}
ServerHandler class (same project package as server code):
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void go() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
So when the client connects to the server, the server implements the ServerHandler class to do the necessary calculations: the idea in doing that was so that multiple clients could connect all at the same time.
So my question is then in two parts:
(1) Have I set up my programs to allow for multi-threading, or have I made a mistake somewhere along the way? (e.g. someone told me I needed to use "Runnable" somewhere to use multi-threading, and I notice I haven't)
(2) After fixing my code to allow for multi-threading, how would I actually use it to let me run my client code in parallel?
Ok for starters, your ServerHandler extends the Thread class. Therefore to make it run as a seperate thread, always invoke by calling the start() method. You are calling you custom go method which will make the ServerHandler execute in the same thread as your infinite while loop. So it should be something like this ServerHandler(socket.accept(),clientNumber).start(). Also it is always better to implement Runnable because java does not support multiple inheritance via the "extends" concept. Therefore in the future if your ServerHandler needs to actually extend a custom class, it wont be able to since it already extends the Thread class. Its better to implement interfaces since there is no limit as to how many you can implement.
Hence implementing the Runnable interface is a good design choice. You can run your client code in parallel by making the client into a threaded model. Here is one such example of multiple client sockets connecting to the server in parallel
Server Code
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client Code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You should use multithreading .
You have to rename method to "run"/ and call that method using "start".Please change Server side code to
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).start();
clientNumber++;
}
}
finally {
socket.close();
}
and client side
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void run() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}
I have a chat program. Now the code works for communicate between client and server via command line. But it gives an exception (java.net.SocketException: Socket is closed) while running. Please help me to fix that problem.
In a java chat program,how will the communication be implemented between client and server?
ie.
client<-->server (between server and client)
or
client A<-->server<-->client B (server act as a bridge between two clients)
Is the 2 way communication can be implemented through a single socket?
Are there any other methods ?
How to communicate more than one client simultaneously?
server code
class Server
{
ServerSocket server;
Socket client;
public Server()
{
try
{
server = new ServerSocket(2000);
System.out.println("\tServer Started..........");
while (true)
{
client = server.accept();
Send objsend = new Send(client);
Recive objrecive = new Recive(client);
//client.close();
}
}
catch (Exception e)
{
System.out.println("Exception4 " + e);
}
}
public static void main(String arg[])
{
new Server();
}
}
class Recive implements Runnable
{
Socket client;
public Recive(Socket client1)
{
client=client1;
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
ObjectInputStream ois;
Message M=new Message();
try
{
ois = new ObjectInputStream(client.getInputStream());
M = (Message)ois.readObject();
M.display();
ois.close();
}
catch (Exception e)
{
System.out.println("Exception1 " + e);
}
}
}
class Send implements Runnable
{
Socket client;
public Send(Socket client1)
{
client=client1;
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
try
{
System.out.println("Me(server)");
M.strmessage=br.readLine();
ObjectOutputStream oos=new ObjectOutputStream(cli ent.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
client code
class Client
{
public static void main(String arg[])
{
try
{
Send objsend=new Send();
Recive objrecive=new Recive();
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Send implements Runnable
{
public Send()
{
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
try
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
while(true)
{
System.out.println("Me(client)");
M.strmessage=br.readLine();
Socket client=new Socket("localhost",2000);
ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Recive implements Runnable
{
public Recive()
{
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
try
{
while(true)
{
Socket client=new Socket("localhost",2000);
ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
Message CNE=(Message)ois.readObject();
CNE.display();
ois.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
First of all, don't close the streams in every run().
Secondly, check whether port for server which you are using is free.
This program makes your pc both host and server.
import java.io.IOException;
import java.net.*;
public class ClientServer {
static byte[] buffer = new byte[100];
private static void runClient() throws IOException {
byte buffer[] = new byte[100];
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds=new DatagramSocket();
int pos = 0;
while (pos<buffer.length) {
int c = System.in.read();
buffer[pos++]=(byte)c;
if ((char)c =='\n')
break;
}
System.out.println("Sending " + pos + " bytes");
ds.send(new DatagramPacket(buffer, pos, address, 3000));
}
private static void runServer() throws IOException {
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(3000, address);
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.print(s);
}
public static void main(String args[]) throws IOException {
if (args.length == 1) {
runClient();
} else {
runServer();
}
}
}
also follow this link
There could be multiple places where the exception could be thrown. Without a stack trace it is difficult to state so accurately, as to the cause of failure.
But the root cause, is essentially due to the fact that you are closing the InputStream of the socket in your Receiver threads after reading a message, and closing the OutputStream of the socket in your Sender threads after sending a message. Closing either of these streams will automatically close the socket, so you if attempt to perform any further operation on it, a SocketException will be thrown.
If you need to ensure that your server and client do not shutdown in such an abrupt manner, you'll have to keep reading the InputStream (until you get a special message to shutdown, for instance). At the same time, you'll also have to keep writing to the OutputStream. Two-way communication is definitely possible, and the posted code is capable of the same (if the socket remains open).
If you have to handle multiple clients, you'll need multiple reader and writer threads on the server, each listening on an instance of a Socket returned from ServerSocket.accept(); in simpler words, you need a reader-writer pair listening on a distinct socket on the server for each client. At the moment, multiple clients can connect to the Server, as each incoming connection is provided its own client Socket object on the Server, that is provided to individual reader and writer threads. The main Server thread can continue to receive incoming connections and delegate the actual work to the reader-writer pairs.
chat programms normaly have a server through which all communication goes. The reason is that other wise every client needs to know how to reach every other client. And that doesn't work in the general case.
So you'll have a server, every client registers and talks with the server, which will forward messages to other clients.
Mostly communication is done via HTTP cause this is likely to go through firewalls and proxies. You probably want to read up on long polling if you are planning for anything serious.
I am facing a probleme with threads and sockets I cant figure it out, if someone can help me please i would really appreciate.
There are the facts :
I have a service class NetworkService, inside this class I have a Socket attribute.
I would like it be at the state of connected for the whole lifecycle of the service.
To connect the socket I do it in a thread, so if the server has to timeout, it would not block my UI thread.
Problem is, into the thread where I connect my socket everything is fine, it is connected and I can talk to my server, once this thread is over and I try to reuse the socket, in another thread, I have the error message Socket is not connected.
Questions are :
- Is the socket automatically disconnected at the end of the thread?
- Is their anyway we can pass back a value from a called thread to the caller ?
Thanks a lot,
Here is my code
public class NetworkService extends Service {
private Socket mSocket = new Socket();
private void _connectSocket(String addr, int port) {
Runnable connect = new connectSocket(this.mSocket, addr, port);
new Thread(connect).start();
}
private void _authentification() {
Runnable auth = new authentification();
new Thread(auth).start();
}
private INetwork.Stub mBinder = new INetwork.Stub() {
#Override
public int doConnect(String addr, int port) throws RemoteException {
_connectSocket(addr, port);
_authentification();
return 0;
}
};
class connectSocket implements Runnable {
String addrSocket;
int portSocket;
int TIMEOUT=5000;
public connectSocket(String addr, int port) {
addrSocket = addr;
portSocket = port;
}
#Override
public void run() {
SocketAddress socketAddress = new InetSocketAddress(addrSocket, portSocket);
try {
mSocket.connect(socketAddress, TIMEOUT);
PrintWriter out = new PrintWriter(mSocket.getOutputStream(), true);
out.println("test42");
Log.i("connectSocket()", "Connection Succesful");
} catch (IOException e) {
Log.e("connectSocket()", e.getMessage());
e.printStackTrace();
}
}
}
class authentification implements Runnable {
private String constructFirstConnectQuery() {
String query = "toto";
return query;
}
#Override
public void run() {
BufferedReader in;
PrintWriter out;
String line = "";
try {
in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
out = new PrintWriter(mSocket.getOutputStream(), true);
out.println(constructFirstConnectQuery());
while (mSocket.isConnected()) {
line = in.readLine();
Log.e("LINE", "[Current]- " + line);
}
}
catch (IOException e) {e.printStackTrace();}
}
}
Define the output stream as a member variable, attach it in your thread, and only close that stream when you're done...
Currently you're opening (and implicitly closing) the output stream within the thread. As the thread dies, it will close that output stream, which in turn may be killing the socket/connection.
If you define the stream outside of the thread, you can attach it within the thread, and close it at a later time such as when the service is asked to terminate.