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.
Related
I followed a few tutorials and found out how to use threads for multithreading socket servers. I've created a Server class that has ClientServiceThread class for clients. When the thread receives a message from the client, how can I access that information using the Server class?
Here is my Server Thread:
public void run(){
game = new Game();
try{
serverSocket = new ServerSocket(port);
System.out.println("Server Started");
}
catch (IOException e){
System.out.println(e);
}
while(true) {
try {
Socket clientSocket = serverSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
threads.add(cliThread);
cliThread.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Here is my ClientServiceThread class:
public void run() {
boolean m_bRunThread = true;
System.out.println("Accepted Client Address - " + socket.getInetAddress().getHostAddress());
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
while(m_bRunThread) {
String clientCommand = in.readUTF();
System.out.println("Client Says :" + clientCommand);
if(!gameStarted) {
out.writeUTF("GAME_ALREADY_STARTED");
out.flush();
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
EDIT 1: Essentially, I'm listening to commands/messages on the client handler threads. I later want to process them into my Server so I can manipulate my Game object through it.
The approach I'd recommend is to pass the game object to the client threads (it has to be thread-safe!), and then let the client threads take the actions on the game object directly. This will simplify your server class, and give you a single place to handle incoming messages.
I'm trying to make a connection between a server and multiple clients, but it doesn't work even for one. All I want to do is to send from the client an object using the ObjectOutputStream class. The connection is made successfully at the beginning but when I try to send the object to the server it fails.
This is the client part which is written in the main method of a class:
Socket socket;
OutputStream out;
ObjectOutputStream fout;
boolean connected=false;
if (!connected) {
try {
socket = new Socket("localhost", 8000);
out = socket.getOutputStream();
fout = new ObjectOutputStream(out);
fout.flush();
connected = true;
fout.writeObject(ac1);//ac is an object of Plane class
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
This is the server:
public class server {
static class ServerThread implements Runnable {
Socket client = null;
public ServerThread(Socket c) {
this.client = c;
}
public void run() {
try {
System.out.println("Connected to client : "+client.getInetAddress().getHostName());
Plane ac=null;
InputStream in=client.getInputStream();
ObjectInputStream fin=new ObjectInputStream(in);
while(client.isConnected()){
ac = (Plane)fin.readObject();
System.out.println(ac.toString());
}
client.close();
} catch (Exception e) {
// System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
ServerSocket server = new ServerSocket(8000);
while (true) {
Socket p = server.accept();
new Thread(new ServerThread(p)).start();
}
} catch (Exception ex) {
System.err.println("Error : " + ex.getMessage());
}
}
}
Could anyone tell me what is the problem?
Your client never closes the socket, and presumably exits, so the connection is reset. So close the socket.
NB isConnected() is not a valid loop condition. It will never become false. Your loop should terminate when EOFExceprion is caught.
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
I have a problem with my application. If I run server and clients on the same computer it works fine. No errors. But if I run server on one PC and I try to connect form other computers I get "timeout exception" or If I manage to connect I will get errors while sending data.
Server code (not all):
// server loop - listening for connections
public void runServer()
{
try {
ServerSocket serverSocket = new ServerSocket(port, 10);
System.out.println("Server up.");
while (true)
{
System.out.println("waiting for new connection...");
Socket socket = serverSocket.accept();
System.out.println("Someone connected");
Thread t = new Thread (new ServerThread(socket));
t.start();
System.out.println("new thread");
}
} catch (IOException ex) {
Logger.getLogger(KsiegarniaServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Server error");
}
// this is thread that is opened when new client connects
private class ServerThread implements Runnable
{
Socket socket;
ObjectInputStream in;
ObjectOutputStream out;
String playerLogin;
int playerID;
public ServerThread(Socket s) {
this.socket = s;
}
public void run() {
try {
Msg m;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("Streams are ready!");
while ( (m = (Msg) in.readObject()).getHeader() != 0 )
{
respondToClient(m); // switch with cases that are running depending on message header
}
} catch (IOException ex) {
//Logger.getLogger(SpaceBattleGameServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("IOException - public void run()");
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException - public void run()");
} finally {
// other stuff
}
I have a program running on a server (Server A) which listens on one port for an external connection (from an external server, B), then listens on another port for an internal connection on the same server (Server A). It then passes data from the internal to external connection and back again.
I want to know if there is a way I can detect that the client external was disconnected. I just need one external connection at a time, but I would like to be able to accept a new one if the external client reboots or something like that.
This socket level stuff is all fairly new to me, so if there is a better way of going about this, I'm all ears. The one stipulation is that the client running on Server B must be the one to initiate the connection and the connection must live for as long as possible.
public void handleConnection() {
System.out.println("Waiting for client message...");
try {
SSLSocket extSocket = (SSLSocket) this.externalServerSocket.accept();
ObjectInputStream externalOis = new ObjectInputStream(extSocket.getInputStream());
ObjectOutputStream externalOos = new ObjectOutputStream(extSocket.getOutputStream());
System.out.println("Client connection establisthed");
// Loop here to accept all internal connections
while (true) {
SSLSocket internalSocket = (SSLSocket) this.internalServerSocket.accept();
new ConnectionHandler(externalOis, externalOos, internalSocket);
}
} catch (IOException e) {
System.err.println(e.getMessage());
return;
}
}
class ConnectionHandler implements Runnable {
private SSLSocket internalSocket;
private ObjectOutputStream internalOos;
private ObjectInputStream internalOis;
private ObjectInputStream externalOis;
private ObjectOutputStream externalOos;
public ConnectionHandler(ObjectInputStream externalOis,
ObjectOutputStream externalOos, SSLSocket internalSocket) {
this.internalSocket = internalSocket;
try {
this.internalOis = new ObjectInputStream(this.internalSocket.getInputStream());
this.internalOos = new ObjectOutputStream(this.internalSocket.getOutputStream());
this.externalOis = externalOis;
this.externalOos = externalOos;
} catch (IOException e) {
System.err.println(e.getMessage());
}
new Thread(this).start();
}
#Override
public void run() {
try
{
// process data
Object o = internalOis.readObject();
externalOos.writeObject(o);
Object o2 = externalOis.readObject();
internalOos.writeObject(02);
internalOos.close();
internalOis.close();
this.internalSocket.close();
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.err.println(e.getMessage());
}
}
}
If the client disconnects, readObject() will throw EOFException, and write() will throw an IOException: connection reset. That's all you need.