I'm new in Java Sockets, I have seen so many examples but I can't understand how to pass an argument from server to client and vice versa. My destination is to pass an Object that's why I'm using Object I/O Stream.
I have to classes Server and Player.
public class Server extends Thread{
public static final int TEST = 165;
ServerSocket serverSocket;
InetAddress address;
Player playerWhite;
public Server() {
start();
}
#Override
public void run() {
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendTestMessage(Player player) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(player.socket.getOutputStream());
testToClient.write(TEST);
testToClient.flush();
}
And the Player class:
public class Player extends Thread {
Socket socket;
Player() throws IOException
{
socket = new Socket(InetAddress.getLocalHost(), 6000);
}
#Override
public void run() {
try {
listenTestStream();
}
catch (IOException | ClassNotFoundException ex)
{
Logger.getLogger(CheckerPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void listenTestStream() throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
int message = ois.readInt();
//To test
System.out.println("Server listened: " + message);
}
I execute it as create a Server object in the other class.
When I have testing this application I saw that sometimes client is faster than Server. Is it possible to make him "wait" for server response?
Thanks for your response.
EDIT 1: PROBLEM SOLUTION:
From outside we should create:
Player player = new Player(); // (class player extends from Thread)
player.start();
and delete the Player variable - is not necessary, we need only Socket so:
Server:
Socket playerWhiteSocket
public void run() {
try
{
serverSocket = new ServerSocket(PORT);
playerWhiteSocket = serverSocket.accept();
sendMessage(playerWhiteSocket, "Hello");
}
catch(IOException | ClassNotFoundException ex)
{}
public void sendMessage(Socket socket, String message) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(socket.getOutputStream());
testToClient.writeObject(message);
testToClient.flush();
}
In Player class we need get method:
public String receiveMessage() throws IOException, ClassNotFoundException
{
//socket is a variable get from Player class socket = new Socket("severHost", PORT);
ObjectInputStream messageFromServer = new ObjectInputStream(socket.getInputStream());
String message = (String) messageFromServer.readObject();
return message;
}
I would recomment doing this public void start(){
try {
ServerSocket = new ServerSocket(this.port,10,this.localAddress);
// set timeout if you want
//this.clientServerSocket.setSoTimeout(timeout);
// infinity loop
while(true)
{
//wait for a client connection
Socket socket = ServerSocket.accept();
// start thread for every new client
Thread t = new Thread(new AcceptClients(this.socket));
t.start();
System.out.println(L"new client connected");
// call garbage collector and hope for the best
System.gc();
}
} catch (IOException e) {
System.out.println("IO Error");
e.printStackTrace();
}
}
and then in another class
public class AcceptClients implements Runnable{
// socket
private Socket socket;
public AcceptClients (Socket socket){
this.socket = socket;
}
#Override
public void run() {
// what happens if a client connect
}
}
I always use this and it works fine
Suggested changes.
Create ServerSocket only once. If you have done it, you won't get "Address already in use" error
After creating Server Socket, you thread should be in while (true) loop to accept connection from client.
Once you create a client socket, pass that socket to thread.
Now Player is used to send communication from server to client socket. So You need one more class like PlayerClient which create a socket to Server IP and Port. Now PlayerClient should create one more thread to handle IO operations like you have done from server. In this case, creating a socket is not in while loop from client side. It create a socket to server once. Now you can run this PlayerClient program from multiple machines.
If you are just sending just primitive type, use DataOutputStream & DataInputStream instead of ObjectStreams
This code will become like this
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
System.out.println("server waits for players");
while ( true){
Socket socket = serverSocket.accept();
Player playerWhite = new Player(socket);
sendTestMessage(socket);// Move this method to Player thread and change the signature of this method accordingly to accept a socket
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Player.java
Player(Socket socket) throws IOException
{
this.socket = socket;
start();
}
Have a look at this chat example for better understanding.
Yep it is.
It should work if you put it in a endlees loop like that:
try
{
while(true){
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
But I would not recommend to put this in a thread. Instead I would put the connection of a new client in a thread, so multiple clients can connect to the server
Related
I have created a server-client project where the server keeps listening and prints the information. However, when i shutdown the client, the server remains open. The problem is that I need to insert this into another application, and, if the server does not close at first, the application will not open unless i kill the process in that port (but this is not an option to me). What should I do to properly close the server once the client disconnects?
Here is the code:
Server:
public class Server {
public static void main(String[] args) {
Connection conn = new Connection();
new Thread(conn).start();
}
private static class Connection implements Runnable {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(5005)) {
Socket socket = serverSocket.accept();
listener(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void listener(Socket socket) throws IOException {
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
boolean alive = true;
while (alive) {
try {
outputStream.writeUTF(new Scanner(System.in).nextLine());
System.out.println(inputStream.readUTF());
} catch (IOException ex) {
ex.printStackTrace();
alive = false;
}
}
}
}
}
Client:
public class Client {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 5005)) {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
System.out.println("Incoming data: " + inputStream.readUTF());
outputStream.writeUTF(new Scanner(System.in).nextLine());
outputStream.flush();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Since now, thank you very much!
The thing that force the system wait and not close is this line at your Server.java :
outputStream.writeUTF(new Scanner(System.in).nextLine());
Once it starts waiting the user input, it waits forever along the life time of the instance although your client is disconnected.
So what you can do ? You can create another thread that makes periodic "ENTER" inputs (if you insist using new Scanner(System.in)) for example input per 5 seconds. After the enter, or any other meaningful input, if you decide this is not from your client, don't write it to the client and wait user input again (if your client still connected !). If your client is not connected, just finish your loop.
Please check Java Robot class and this example
I have a server application that opens a socket and then listens to any connections being made on that socket.
public Server(){
try {
ServerSocket sSocket = new ServerSocket(nPort);
System.out.println("Server started at: " + new Date());
System.out.println("===============================================\n");
//Loop that runs server functions
while(true) {
//Wait for a client to connect
Socket socket = sSocket.accept();
socket.setSoTimeout(30000);
//Create a new custom thread to handle the connection
ClientThread cT = new ClientThread(socket, nPort);
//Start the thread!
new Thread(cT).start();
}
}
catch(IOException ex) {ex.printStackTrace();}
}
Whenever new connection attempted, a new thread is started using the ClientThread class. The ClientThread class has a run method that does all the things need to be done (read input, send respons etc.)
public class ClientThread implements Runnable{
private Socket threadSocket;
private int nPort = 0, maxCon = 2;
//This constructor will be passed the socket
public ClientThread_v3(Socket socket, int port){
threadSocket = socket;
nPort = port;
}
public void run(){
System.out.println("New connection at " + new Date() + "\n");
try {
DataInputStream in = new DataInputStream (threadSocket.getInputStream());
out = new DataOutputStream (threadSocket.getOutputStream());
while (running){
// do some stuff ....
// go to sleep
Thread.sleep(1000);
}
}
catch (IOException ex) {ex.printStackTrace();}
catch (InterruptedException ex) {ex.printStackTrace();}
finally {
try {
threadSocket.close();
System.out.println("Connection closed.\n");
} catch (IOException ex) {ex.printStackTrace();}
}
}}
My question is how do i make the socket connection secure? how do i open a secure connection?
I don't want to use any HTTP packages for that matter, want to keep it as a socket connection.
Any help would be appreciated. Thank you.
I've got a simple client and server that I've written to teach myself a bit of networking. The way it's set up is I've got a main server class which will deal with creating/destroying sockets, and the ConnectionThread class that represents each connection (each of which is given its own thread). The client is super simple.
The problem lies in creating the input/output streams in the ConnectionThread class. I'm not sure exactly what the problem is, but it crashes when the simple test client tries to connect, giving me this:
~~MMO Server Alpha .1~~
Constructed Server
Server Initialized, preparing to start...
Server preparing to check if it should be listening...
Server should be listening, continuing as planned.
ServerSocket passed to ConnectionThread: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=6969]
Constructing ConnectionThread.
Socket[addr=/10.0.1.10,port=55332,localport=6969]
ConnectionThread constructed.
Exception in thread "main" java.lang.NullPointerException
at ConnectionThread.init(ConnectionThread.java:65)
at Server.listen(Server.java:98)
at Server.start(Server.java:62)
at Server.main(Server.java:122)
ConnectionThread added to queue.
Establishing in and out streams:
null
Here are the classes (amended for brevity):
public class Server {
int PORT;
boolean shouldListen;
ArrayList<ConnectionThread> connections = new ArrayList<ConnectionThread>();
ServerSocket serverSocket;
public Server() {
try {
PORT = 6969;
shouldListen = true;
serverSocket = new ServerSocket(PORT);
}
catch (IOException e) {
System.out.println("Error in server constructor.");
System.exit(1);
}
}
public void start() {
System.out.println("Server preparing to check if it should be listening...");
listen();
System.out.println("Server finished listening.");
}
public void listen() {
while (shouldListen) {
ConnectionThread conn = null;
System.out.println("Server should be listening, continuing as planned.");
try {
conn = new ConnectionThread(serverSocket);
}
catch (Exception e) {
System.out.println("____Error constructing ConnectionThread. Could there be another instance of the server running?");
System.exit(1);
}
System.out.println("ConnectionThread constructed.");
connections.add(conn);
System.out.println("ConnectionThread added to queue.");
conn.init();
System.out.println("Finished ConnectionThread initialization, verifying...");
if (conn.isInitialized) {
System.out.println("ConnectionThread Initialized, preparing to start new thread.");
(new Thread(conn)).start();
}
}
}
public static void main(String[] args) {
System.out.println("~~MMO Server Alpha .1~~");
Server server = new Server();
System.out.println("Constructed Server");
server.init();
System.out.println("Server Initialized, preparing to start...");
server.start();
}
}
Here's the ConnectionThread class:
public class ConnectionThread implements Runnable {
boolean shouldBeListening = true;
boolean isThereAnUnsentOutgoingMessage = false;
String outgoingMessage = "OUTGOING UNINITIALIZED";
boolean IsThereAnUnsentIncomingMessage = false;
String incomingMessage = "INCOMING UNITIALIZED";
boolean isInitialized = false;
PrintWriter out;
BufferedReader in;
String currentInputMessage = "Test Input Message from the Server ConnectionThread";
String previousInputMessage = null;
Socket socket;
public ConnectionThread(ServerSocket s) {
System.out.println("ServerSocket passed to ConnectionThread: " + s);
/*
* The purpose of the constructor is to establish a socket
* as soon as possible. All transmissions/logic/anything else
* should happen in init() and/or run().
*/
System.out.println("Constructing ConnectionThread.");
try {
Socket socket = s.accept();
System.out.println(socket);
}
catch (IOException e) {
System.out.println("Error in ConnectionThread constructor");
System.exit(1);
}
}
public void init() {
/*
* Everything should be set up here before run is called.
* Once init is finished, run() should be set to begin work.
* This is to ensure each packet is efficiently processed.
*/
try {
System.out.println("Establishing in and out streams:");
System.out.println(socket);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("ConnectionThread: Output Stream (PrintWriter) Established");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("ConnectionThread: InputStream (BufferedReader) Established");
}
catch (IOException e) {
System.out.println("Error in ConnectionThread method Init.");
System.exit(1);
}
isInitialized = true;
}
And optionally, here's the test client:
public class TestClient {
static PrintWriter out;
BufferedReader in;
public final int PORT = 6969;
Socket socket = null;
InetAddress host = null;
public TestClient() {
out = null;
in = null;
socket = null;
host = null;
}
public void connectToServer() {
System.out.println("Connecting to server...");
try {
host = InetAddress.getLocalHost();
socket = new Socket(host.getHostName(), PORT);
}
catch (Exception e) {
System.out.println("Error establishing host/socket");
System.exit(1);
}
try {
System.out.println("Establishing I/O Streams");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (Exception e) {
System.out.println("Error establishing in/out streams");
System.exit(1);
}
}
public static void main(String[] args) {
System.out.println("~~TestClient Alpha .1~~");
TestClient c = new TestClient();
c.connectToServer();
System.out.println("Should be connected to server. Sending test message...");
while (true) {
System.out.println("here");
out.println("Hello there");
}
}
}
The 'socket' variable in the constructor of ConnectionThread shouldn't be local. It is shadowing the member variable.
It is customary to call accept() in the listen() loop, and pass the accepted socket to the ConnectionThread.
As EJP said, in your ConnectionThread constructor you think that you are assigning the value to the socket field, however you are actually assigning the value to the socket method variable, thus the socket field remains null, and in init() you see socket as null.
In addition to EJP answer: you did not provide ConnectionThread.run() method, but I assume you are going to use fields in, out and socket in your run() method. Since these fields are not marked as volatile or final, depending on your luck and number of core on your computer, you may also get NullPointerException at run() method.
This is because new variable value may be not propagated between caches and new thread will not see value of changed.
Explanation of this possible problem is here - The code example which can prove "volatile" declare should be used
I'm trying to make a simple ECHO server that can manage more client.
Server Class:
public class EchoServer {
protected int port ;
protected ServerSocket socket;
private Socket acceptedSocket;
public EchoServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
}
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket = socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
}
Runnable client handler:
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter From_Server = null;
BufferedReader To_Server = null;
String to_server_string = null;
try {
From_Server = new PrintWriter(socket.getOutputStream());
To_Server =
new BufferedReader(
new InputStreamReader( socket.getInputStream()));
System.out.println("Stream opened.\n");
while(true) {
if(To_Server.ready()){
System.out.println("Reading input line.\n");
to_server_string = To_Server.readLine();
if(to_server_string.equalsIgnoreCase("quit")) {
System.out.println("Connection closed on user request.\n");
From_Server.print("Bye :)\n");
From_Server.close();
To_Server.close();
socket.close();
}
else {
System.out.println(
"String '" +
to_server_string+"' is not 'quit', echoing.\n");
From_Server.print("ECHO: "+to_server_string+"\n");
System.out.println("String written on stream, flushing.\n");
From_Server.flush();
}
}
}
}
catch (IOException e) {
System.out.println("Stream error (connection closed?).\n");
}
}
}
Main Class
public static void main(String[] args) {
try {
EchoServer server= new EchoServer(9999);
server.start();
}
catch (IOException ex) {
System.out.println("Unable to start server (port is busy?)\n");
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (AcceptingClientException e){
System.out.println("Unable to accept client\n");
}
}
More than one client is able to connect to the server, but the ECHO will works only with one client at the time (if I close the connection with one client the server will start to handle another one automatically), but I can't understand why: when a client connects to the server, the associated socked created with server.accept() is passed to a new instance of a runnable client handler which is started with handler.run() and the server should go back on waiting in server.accept() (unless the ServerSocket is closed).
I'm assuming the issue should be with this method of the server class:
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket=socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
But I can't figure out what is wrong with it...what am I missing?
Your code:
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
doesn't start a new thread, it delegates to ClientHandler.run() in the same thread.
To start a thread, use new Thread( ch ).start(); since ch is of class ClientHandler which implements Runnable.
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.