I am creating a multi client chat server and i am pretty confident that it will work (Correct me if i'm wrong), I have the issue that on the socket that the client connects to is null so the connections can't be created because i use if(Socket != null) so i don't get errors but i will explain my layout real fast. The server starts with a starter class called (LaunchServer) that uses the class object ClientConnector as Minecraft and then starts the method runServer(). Here is the code for this class:
public class LaunchServer
{
public static void main(String[] args)
{
System.out.println("[Info] Running");
ClientConnector Minecraft = new ClientConnector();
Minecraft.runServer();
}
}
It's fairly simple. This brings us to the ClientConnector class. Here we start at the method runServer(). Right away we have a try catch block. in that block we print a message that the server is trying to connect to the port 1337. we then create a new ServerSocket called serversocket. We then send a message to the console saying that we have bound to port and that we are awaiting a connection. While true, we create a new Socket socket that equals ServerSocket.accept(); OMG fuck it. Heres the code. you know what it does...
import java.util.ArrayList;
import java.net.*;
import java.io.*;
public class ClientConnector
{
public static ArrayList<Socket> Connections = new ArrayList<Socket>();
public static void runServer()
{
try
{
System.out.println("[Info] Attempting to bind to port 1337.");
#SuppressWarnings("resource")
ServerSocket serversocket = new ServerSocket(1337);
System.out.println("[Info] Bound to port 1337.");
System.out.println("[Info] Waiting for client connections...");
while(true)
{
Socket socket = serversocket.accept();
new ClientHandler(socket).start();
Connections.add(socket);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
This takes us to the handler class:
import java.io.*;
import java.net.*;
public class ClientHandler extends Thread
{
Socket Socket;
public ClientHandler(Socket socket)
{
socket = Socket;
System.out.println("[Info] Client connected on port 1337.");
}
public void run()
{
while(true)
{
for(int i = 0; i < ClientConnector.Connections.size(); i++)
{
try
{
if(Socket != null)//This stays null...
{
ObjectOutputStream Output = new //These can't be created...
ObjectOutputStream(Socket.getOutputStream());
ObjectInputStream Input = new ObjectInputStream(Socket.getInputStream());
whileChatting(Input, Output);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public static void sendMessage(String message, String returnedMessage, ObjectOutputStream out)
{
try
{
if(!message.isEmpty())
{
out.writeObject("\247c[Server]\247d " + message);
out.flush();
System.out.println("[Chat] Sent: " + message);
}
else
{
out.writeObject(returnedMessage);
System.out.println("[Chat] Sent: " + returnedMessage);
}
out.flush();
System.out.println("[Info] Fluching remaining data to stream.");
System.out.println("\n[Server] " + message);
}
catch(IOException ioException)
{
System.out.println("[Warning] Error: ioException # sendMessage line 76.");
}
}
public static void whileChatting(ObjectInputStream input, ObjectOutputStream output) throws IOException
{
String message = "";
do
{
try
{
message = (String) input.readObject();
System.out.println("\n" + message);
sendMessage("", message, output);
}
catch(ClassNotFoundException classNotFoundException)
{
System.out.println("[Warning] Error: ClassNotFoundException # whileChatting line 1-7.");
System.out.println("\n idk wtf that user sent!");
}
}while(!message.equals("/stop"));
}
}
Read the run method. There you will see the null problem
Would the connection get accepted then passed to the hander class? How can a null connection get accepted? My question is how can i fix this problem?
The problem is you've got a logic error due to un-recommended naming conventions. You shouldn't name variables with keywords, like your Socket variable, and each variable should have a distinguishable name. e.g. not socket1, socket2 but serverSocket, clientSocket because that will make it easier for you and anyone else to read and fix your code.
Change
Socket Socket;
to
Socket connectedSocket;
and in your constructor
socket = Socket;
to
connectedSocket = socket;
then finally, in your run() method change
if(Socket != null)
to
if(connectedSocket != null)
Related
I am trying to open a socket inside a bukkit plugin so i could send data to it using php or node but instead of socket remaining open after one use it just closes and also server does not load before this happens what should i do i am out of ideas.
Main:
public class Main extends JavaPlugin {
public void onEnable() {
saveDefaultConfig();
getConfig().options().copyDefaults(true);
System.out.println("[INFO] Main class loaded.");
start();
}
public void start() {
SocketServer server = new SocketServer();
try {
server.start(getConfig().getInt("port"), getConfig().getString("socket-password"));
System.out.println("[INFO] Main successfully called start.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket server class:
When called this should read information convert it into array check the first item in array and use it as auth code then array should be converted into string and used in Command executor class. This works fine but after one use this just closes
public class SocketServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port, String socketpwd) throws IOException {
System.out.println("[INFO] Socket server listening on: " + port);
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Boolean enabled = true;
try {
// Socket authentication
String message = in.readLine();
String suffix[] = message.split(" ");
System.out.println("Socket auth code used: "+ suffix[0]);
System.out.println("Socket pwd is: " + socketpwd);
if (socketpwd.equals(suffix[0])) {
out.println("Auth sucessfull!");
// do the following command from args here
String command = suffix[1];
int suffixL = suffix.length;
// add arguments to command
for (int i = 2; i < suffixL; i++) {
command = command + " " + suffix[i];
}
// call req exec
System.out.println("[INFO] Socket server contacted Request executor with: " + command);
RequestExecutor.executor(command);
enabled = false;
}
else {
out.println("Unrecognised auth code!");
}
} catch (NullPointerException e) {
System.out.println("Exception prevented!");
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
Other problem as i mentioned is that bukkit server does not fully load before one request has been made to this socket.
Thank you for your help.
First of all you shouldn't be running a socket like that on the main thread, typically you should be running this on an async task using the Bukkit scheduler.
Then once you open the socket you should create a while loop to continuously poll for a connection and handle the incoming data. Instead what you are doing is opening the socket, reading a line and then dropping the connection.
You want to be doing something similar to
while(true){
Socket socket = serverSocket.accept();
}
See this webpage for some more info.
This is the Problem Statement i Was Given :
Design a protocol where a server is responsible to match up two chatt clients. The server listens on a TCP port for upcoming connections.
If no client is already connected to the server to be paired, the server accepts the connecting client, and makes it wait for another client. To do that, it sends a message to the connecting client to wait. When recieving this command the client constructs another Server Socket instance to listen on a port . The client then sends a mesagge to the server that contains the port number in which the newly created server listens on.
When another client, C2, seeks a connection with the server while C1 is waiting, the server informs C2 the existence of C1 by sending a message “PEER_LOC $h:$p” to C2, where $h is the host name (or IP address) of C1 and $p is the port number on which C1 is waiting. After C2 receives this message, it seeks a connection to C1 using the obtained information.Clients get the messages from users. The two clients then exchange messages until either party sends an end of stream” (Ctrl-D in Linux). Their conservation is then terminated.Sophisticated methods may employ multiple threads, timeouts, etc., and is not required in this problem.
My issues is connecting two clients to my Server. I run my server program and then two other clients classes that are duplicated of each other only with different names. I can connect to one of them only the other one just seems to wait forever.
Theses are my classes I run.
The server:
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Server {
private static ObjectOutputStream output; // stream data out
private static ObjectInputStream input; // stream data in
private static ServerSocket server;
private static Socket connection; // socket means set up connetion between 2 computers
private static int n;
//Constructor
public static void main(String[] args) throws IOException {
Server obj = new Server();
obj.RunServer();
try {
while (true) {
Handler obj2 = new Handler();
obj2.start();
System.out.println("Accepted connection from "
+ connection.getInetAddress() + " at port "
+ connection.getPort());
n++;
System.out.println("Count " + n);
}
} finally {
connection.close();
}
}
public Server() {
}
// run the server after gui created
public void RunServer() {
try {
server = new ServerSocket(6789); // 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
waitForConnection(); // wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
private void waitForConnection() {
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "WAIT ";
sendMessage(message);
do {
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("Message from Client " + message);
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
try {
output.close();
input.close();
connection.close();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush();
System.out.println("Message to client " + message);
} catch (IOException ioexception) {
}
}
public static class Handler extends Thread {
private Socket connection;
public Handler() {
String message = "WAIT";
}
public void run() {
System.out.println("Connect" + Server.connection);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForConnection() {
System.out.println("server" + server);
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
System.out.println("Connection" + connection);
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
private void whileChatting() throws IOException {
String message = " You are now connected ";
sendMessage(message);
do {
try {
message = (String) input.readObject();
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));
}
private void closeChat() {
try {
output.close();
input.close();
connection.close();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
static private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush();
} catch (IOException ioexception) {
}
}
}
}
The and one duplicated client classes C1, or C2:
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Client1 extends JFrame {
private JTextField userInput; //
private JTextArea theChatWindow; //
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private Socket connection; // socket means set up connetion between 2 computers
//Constructor
public Client1() {
}
// run the server after gui created
public void RunClient() {
try {
connection = new Socket("localhost", 6789);// 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
// wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
} finally {
closeChat();
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "";
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("message " + message);
if (message.equals("WAIT")) {
ServerSocket server2 = new ServerSocket(5000);
System.out.println("Hello");
message = "5000";
sendMessage(message);
}
System.out.println("From server " + message);
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(" - " + message);
output.flush(); // send all data out
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
//
//
public static void main(String[] args) {
Client1 obj = new Client1();
obj.RunClient();
}
}
I can connect to the first Client i run the second client waits for ever.
Any Suggestions or comments would be appreciated.
You're blocking server cycle. You should start new thread for each connection from client. I would separate waitForConnection() from downstream code in server's loop in RunServer method. So your while loop there should look like:
public static void RunClient() {
...
while (true) {
try {
final Server srv = waitForConnection(); // wait for a connection between 2 computers
new Thread(new Runnable() {
public void run() {
try {
srv.setupStreams(); // set up a stream connection between 2 computers to communicate
srv.whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException ex) {
// ex.printStackTrace();
}
}
}).start();
} catch (EOFException eofException) {
}
}
In this case you have to make Server instance for each client and your server declaration should contain non-static props related to client like:
public class Server {
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private static ServerSocket server;
private Socket connection; // socket means set up connetion between 2 computers
...
And Server creation should happen inside waitForConnection() like:
private static Server waitForConnection() {
try {
Socket connection = server.accept();
return new Server(connection);
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
It's not the only way to do it. You may preserve Server class for being responsible for running main cycle in the same instance. But in this case I would create some additional class handling properties related to connection from particular client (connection, input, output).
This might help you think to bring it down to the essence, or it might not, I don't know really.
i
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server implements Runnable{
private final ServerSocket serverSocket;
private Socket clientBuffer;
public Server(int port) throws IOException {
this.serverSocket = new ServerSocket(port);
}
#Override
public void run() {
while(true) {
try {
if(clientBuffer != null) {
//Accept new connection and echo ip and port, as the assignment tells you to, then set clientBuffer to null and start the process again. Change Client accordingly.
}
} catch(Exception ex) {
System.err.println(ex.getMessage());
System.exit(1);
}
}
}
}
I am sorry, I have searched but seem that all the answers dont fix my problem. I got this error when trying to create a ServerSocket to reply to multiple client message.
My server code:
package Server;
import java.net.*;
import java.io.*;
public class Server {
public final static int defaultPort = 7;
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(defaultPort);
int i = 0;
while (true) {
try {
System.out.println("Server is running on port "
+ defaultPort);
Socket s = ss.accept();
System.out.println("Client " + i + " connected");
RequestProcessing rp = new RequestProcessing(s, i);
i++;
rp.start();
} catch (IOException e) {
System.out.println("Connection Error: " + e);
}
}
} catch (IOException e) {
System.err.println("Create Socket Error: " + e);
} finally {
}
}
}
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
DatagramSocket ds = new DatagramSocket(7);
while (true) {
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
String theString = new String(incoming.getData(), 0,
incoming.getLength());
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
ds.close();
break;
}
theString = theString.toUpperCase();
DatagramPacket outsending = new DatagramPacket(
theString.getBytes(), incoming.getLength(),
incoming.getAddress(), incoming.getPort());
System.out.println("Server reply to Client "
+ clientNo + ": " + theString);
ds.send(outsending);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
and my Client code:
package Client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
public class Client extends Object {
public final static int serverPort = 7;
public static void main(String[] args) {
try {
DatagramSocket ds = new DatagramSocket();
InetAddress server = InetAddress.getByName("192.168.109.128");
Socket s = new Socket("192.168.109.128", 7);
String theString = "";
do {
System.out.print("Enter message: ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
theString = br.readLine();
byte[] data = theString.getBytes();
DatagramPacket dp = new DatagramPacket(data, data.length,
server, serverPort);
ds.send(dp);
System.out.println("Sent to server server: " + theString);
byte[] buffer = new byte[6000];
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
System.out.print("Server reply: ");
System.out.println(new String(incoming.getData(), 0, incoming
.getLength()));
} while (!"quit".equals(theString));
s.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
With the first Client connect, it works smoothly. But from the second Client, it throws java.net.BindException: Address already in use: Cannot bind.
Second Client can also send and receive message, but the Client No is still 0.
Server is running on port 7
Client 0 connected
Server is running on port 7
Client 0 sent: msg 0
Server reply to Client 0: MSG 0
Client 1 connected
Server is running on port 7
java.net.BindException: Address already in use: Cannot bind
Client 0 sent: msg 1 <<-- this one is sent from client 1 but Client No is 0
Server reply to Client 0: MSG 1
So, in RequestProcessing.run you decide to ignore the socket received at constructor and open a DatagramSocket on the same port as the one you are listening. What did you expect it will happen?
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
// *****************
// The processor should be using this socket to communicate
// with a connected client *using TCP Streams*
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
// *****************************
// But, instead of using the this.channel, your code
// decides to ignore the TCP socket,
// then open another UDP *"server-side like"* socket.
// First time it's OK, but the second thread attempting
// to open another DatagramSocket on the same port will fail.
// It's like attempting to open two TCP ServerSockets on the
// same port
DatagramSocket ds = new DatagramSocket(7);
[Extra]
You will need to decide what protocol you'll be using: if you use a ServerSocket/Socket pair, then probably you want TCP communications, so no DatagramSockets.
If you want UDP communication, the ServerSocket/Socket has little to do with your approach and you'll need to use DatagramSocket. Construct it:
with a port on the serverside - and do it only once.
without any port for the client side then qualify each and every DatagramPackets with the server address and port.
See a tutorial on Oracle site on Datagram client/server configurations.
Everytime you receive a new client TCP connection on your main server socket, you spin up another instance of a RequestProcessing class. The first time you start the RequestProcessing instance thread, it successfully binds to UDP port 7. But then the second client connects and you try to spin up another instance of RequestProcessing while another one already exists. That's not going to work.
You should probably amend you protocol such that the RequestProcessing class picks a new port each time and signals back through to the TCP socket which port was chosen.
But if it was me, I would do this. Have a single RequestProcessing instance for all clients. Given that your UDP echo socket is just sending back a response to the address from which the packet arrived from, you only need one instance of this class.
A TCP solution:
An utility class (I'm too lazy to write the same code in multiple places):
public class SocketRW {
Socket socket;
BufferedReader in;
PrintWriter out;
public SocketRW(Socket socket)
throws IOException
{
super();
this.socket = socket;
if(null!=socket) {
this.in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out=new PrintWriter(socket.getOutputStream());
}
}
public String readLine()
throws IOException {
return this.in.readLine();
}
public void println(String str) {
this.out.println(str);
}
public Socket getSocket() {
return socket;
}
public BufferedReader getIn() {
return in;
}
public PrintWriter getOut() {
return out;
}
}
Server code - no more datagrams, just using Input/Output streams from the sockets, wrapped as Reader/Writer using the utility
public class TCPServer
implements Runnable // in case you want to run the server on a separate thread
{
ServerSocket listenOnThis;
public TCPServer(int port)
throws IOException {
this.listenOnThis=new ServerSocket(port);
}
#Override
public void run() {
int client=0;
while(true) {
try {
Socket clientConn=this.listenOnThis.accept();
RequestProcessing processor=new RequestProcessing(clientConn, client++);
processor.start();
} catch (IOException e) {
break;
}
}
}
static public void main(String args[]) {
// port to be provided as the first CLI option
TCPServer server=new TCPServer(Integer.valueOf(args[0]));
server.run(); // or spawn it on another thread
}
}
class RequestProcessing extends Thread {
Socket channel;
int clientNo;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
SocketRW utility=new SocketRW(this.channel);
while (true) {
String theString=utility.readLine().trim();
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
this.channel.close();
break;
}
theString = theString.toUpperCase();
utility.println(theString);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
Client code - no more datagram sockets, using the same IO streams of the socket.
class TCPClient
implements Runnable // just in case you want to run multithreaded clients
{
Socket socket;
public TCPClient(InetAddress serverAddr, int port)
throws IOException {
this.socket=new Socket(serverAddr, port);
}
public void run() {
String theString="";
InputStreamReader isr = new InputStreamReader(System.in);
try {
SocketRW utility=new SocketRW(this.socket);
BufferedReader br = new BufferedReader(isr);
do {
System.out.print("Enter message: ");
theString = br.readLine().trim();
utility.println(theString);
System.out.println("Sent to server server: " + theString);
String received=utility.readLine();
System.out.println("Server reply: "+received);
} while (!"quit".equals(theString));
}
catch(IOException e) {
e.printStackTrace();
}
}
static public void main(String[] args) {
int port=Integer.valueOf(args[0]); // will throw if its no OK.
TCPClient client=new TCPClient(
InetAddress.getByName("192.168.109.128"),
port
);
client.run();
}
}
I am currently implementing a multithreaded proxy server in java which will accept messages from clients and forward them to another server which will then acknowledge the reception of the message. However, i'm having trouble doing so. Could someone point out what i am doing wrong? Thanks.
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client{
public static void main(String[] args)
{
try
{
Socket client = new Socket(InetAddress.getLocalHost(), 6789);
if(client.isBound())
{
System.out.println("Successfully connected on port 6789");
}
Scanner scanner = new Scanner(System.in);
DataInputStream inFromProxy = new DataInputStream(client.getInputStream());
DataOutputStream outToProxy = new DataOutputStream(client.getOutputStream());
while(true)
{
String message;
System.out.print("Enter your message: ");
message = scanner.next();
outToProxy.writeUTF(message);
System.out.println(inFromProxy.readUTF());
}
}
catch(IOException io)
{
System.err.println("IOException: " + io.getMessage());
System.exit(2);
}
}
}
The server code Server.java:
import java.io.*;
import java.net.*;
/**
* the client send a String to the server the server returns it in UPPERCASE thats all
*/
public class Server {
public static void main(String[] args)
{
try
{
ServerSocket server = new ServerSocket(6780);
if(server.isBound())
{
System.out.println("Server successfully connected on port 6780");
}
Socket client = null;
while(true)
{
client = server.accept();
if(client.isConnected())
{
System.out.println("Proxy is connected");
}
DataInputStream inFromProxy = new DataInputStream(client.getInputStream());
DataOutputStream outToProxy = new DataOutputStream(client.getOutputStream());
System.out.println(inFromProxy.readUTF());
outToProxy.writeUTF("Message has been acknowledged!");
}
}
catch(IOException io)
{
System.err.println("IOException: " + io.getMessage());
System.exit(2);
}
}
}
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
public class Proxy{
public static ServerSocket server = null;
public static Socket client = null;
public static void main(String[] args)
{
try
{
server = new ServerSocket(6789);
Socket clientsocket = null;
while(true)
{
client = server.accept();
if(client.isConnected())
{
System.out.println("Proxy is currently listening to client on port 6789");
}
clientsocket = new Socket(InetAddress.getLocalHost(), 6780);
Thread t1 = new ProxyHandler(client, clientsocket);
t1.start();
if(clientsocket.isBound())
{
System.out.println("Clientsocket successfully connected on port 6780");
}
Thread t2 = new ProxyHandler(clientsocket, client);
t2.start();
}
}
catch(IOException io)
{
System.err.println("IOException: " + io.getMessage());
}
}
}
The Proxy code is:
import java.io.*;
import java.net.*;
public class ProxyHandler extends Thread {
private Socket socket;
private String message;
public ProxyHandler(Socket socket, Socket clientsocket)
{
this.socket = socket;
}
public void run()
{
message = "";
try
{
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
while(true)
{
message = in.readUTF();
out.writeUTF(message);
System.out.println(message);
}
}
catch(IOException io)
{
System.err.println("IOException: " + io.getMessage());
System.exit(2);
}
}
}
There is no multithreading here. There should be. Each accepted socket should be entirely processed in its own thread, in both the server and the proxy.
There is no point in testing isBound() immediately after creating and connecting a Socket. It will never be false.
There is no point in testing isConnected() immediately after an accept(). It will never be false.
The server must close each accepted socket once it is finished with it, i.e. once it has EOS from it (read() returns -1).
The proxy must also close each accepted socket once it is finished with it, ditto.
A proxy of any kind should just copy bytes. It shouldn't make assumptions about the format of the data. Don't use readUTF(), use count = read(byte[]) and write(buffer, 0, count). That also means that you don't need DataInput/OutputStreams in the proxy.
Here is the server code
package echoserver;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) {
try {
//establish server socket
ServerSocket s = new ServerSocket(1981);
//Thread client connectionsincoming
while (true) {
//wait for incoming connection
Socket incoming = s.accept();
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package echoserver;
import java.net.*;
import java.util.*;
import java.io.*;
class ThreadedEchoHandler implements Runnable {
public ThreadedEchoHandler(Socket i) {
//initializing socket
incoming = i;
}
public void run() {
try {
try {
//recieve input stream from socket
InputStream inStream = incoming.getInputStream();
//recieve output stream from socket
OutputStream outStream = incoming.getOutputStream();
//Create a scanner from input stream
Scanner scan = new Scanner(inStream);
//Create printer writer from output stream and enabled auto flushing
PrintWriter out = new PrintWriter(outStream, true);
//prompt users on how to exit program soon as a long in into the server
out.println("Enter BYE to exit");
boolean done = false;
//while done is not true and scanner has next line loop
while (!done && scan.hasNextLine()) {
//reading text that came in from the socket
String line = scan.nextLine();
//On the server print the ip address of where the text is coming from and the text they typed
System.out.println("Recieved from " + incoming.getInetAddress().getHostAddress() + ": " + line);
//Echo back the text the client typed to the client
out.println("Echo: " + line);
//if they type BYE in caps terminate there connection and I also trimmed whitespaces
if (line.trim().equals("BYE")) {
done = true;
}
}
} //finally close the socket connection
finally {
incoming.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket incoming;
}
and here is the code for client
package client;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws IOException {
PrintWriter out = null;
try {
Socket s = new Socket(InetAddress.getLocalHost(), 1981);
System.out.println("Connected to server on port 1981");
out = new PrintWriter(s.getOutputStream());
out.println("Hello");
s.close();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
Socktes are getting created successfully but when control goes to t.start() method call it is not calling run() method of ThreadedEchoHandler class.
Why is this happening? any idea?
The client writes "Hello" to the PrintWriter. So far, so good.
You may expect that the PrintWriter sends this text directly to the socket, but it doesn't. The documentation from the PrintWriter(OutputStream) constructor says that it creates a PrintWriter without automatic line flushing. This means that you have to call out.flush() whenever you want something to be actually sent.
Until you call out.flush() the text only exists in some internal buffer, and the server will not be able to see it.
My guess would be that the acept statement is blocking forever because no client is connecting to the server. You could wrap accept() in prints to prove or disprove.