How to make public connections in java - java

I am making a public connection for a computer
So I was making a connection between two computers in java.
The Code for Client is:-
public class Client {
Socket socket = null;
ServerSocket server = null;
DataInputStream input = null;
DataInputStream in = null; // second is because one takes input from user and one from socket
DataOutputStream output = null;
public Client(String addr,int port)
{
try
{
socket = new Socket(addr,port); //Specifies address and port to connect
input = new DataInputStream(System.in);
output = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//Code to read coming messages continously and printing them
Runnable read = new Runnable(){
public void run()
{
String line = "";
while (!line.equals("over") // means will work until "over" is recieved
{
line = in.readUTF();
System.out.println("Message Came: "+line);
}
Thread.currentThread().stop(); //To stop current thread so there is no error looping
};
Thread thread = new Thread(read);
thread.start();
String line = ""; //To read message from user
while(!line.equals("over"))
{
line = input.readLine();
output.writeUTF(line);
}
// CLosing connection
socket.close();
in.close();
input.close();
output.close();
}catch(Execption e){
return; // loop for trying again and again to connect
}
}
public static void main(String []args)
{
Client client = new Client("192.168.1.7",25565);
}
}
So this is all the code for Client
All code is same for server except declaring things and initializing them
Constructer will have 1 value (port)
ServerSocket server = null;
While initializing :-
server = new ServerSocket(port);
socket = server.accept();
All works fine until I am using local conne tion that is my ipv4 address
I know I have to port forward the port I am using and I have enabled it
But when I use public ip then it doesnot works

Related

Java Sockets - Client message not reaching Server

currently I am trying to send multiple messages from a client to a server and echo them on the server but somehow my message is not arriving at the server until i press CTRL+Z(D) and hit enter.
My loop runs as long as the user does not enter "quit" but altough I write my message to the OutputStream and flush it my message does not show on the Server side as if my Client still reads input.
(I do not want to use BufferedReaders or Threads at the moment it's purely for learning reasons.)
Would be nice if someone could tell me where my mistake/error lies.
Read also the javadocs but still can not find my mistake.
Client.java
public class Client {
//class members
private String msg = null;
private Scanner scn = null;
public Client(String ip, int port) throws IOException {
//Connect to Server
try(Socket socket = new Socket(ip,port))
{
//Initialize class members
scn = new Scanner(System.in); //Init Scanner
msg="";
System.out.println("Enter message:");
//Write to Socket
OutputStream out = socket.getOutputStream();
while(!msg.equals("quit"))
{
msg=scn.nextLine();
out.write(msg.getBytes(), 0, msg.length());
out.flush();
}
}
catch (IOException ex)
{
System.err.println(ex);
}
}
Server.java
public class Server {
//class members
private String msg = null;
public Server(int port) throws IOException {
//Setup ServerSocket.
ServerSocket server = new ServerSocket(port);
System.out.println("SERVER: Launched service.");
//Accept incoming connection requests.
while(true) {
try(Socket connection = server.accept())
{
System.out.println("SERVER: Client connection accepted.");
//Read Input
StringBuilder line = new StringBuilder();
InputStream in = connection.getInputStream();
for(int c=in.read(); c!=-1; c=in.read())
{
line.append((char) c);
}
System.out.println(line);
}
catch (IOException ex)
{
System.out.println("SERVER: Client disconnected!");
}
}
}
sincerely,
rhyleigh
Your server prints nothing until read() returns -1.
read() returns -1 at end of stream.
Over a TCP socket, end of stream is only caused by the peer closing the connection.
Your server's peer, i.e. the client, doesn't close the connection until you type ^Z at the terminal. which causes an unstated exception to be thrown.
Your program is working as designed.

Java Socket - how to check if the ServerSocket is already in use by another client

I have this client and server programs.
The client get a command from user, and send it to the server, and the server return the result (output of the command) to the client.
I have 2 classes Command and CommandResult (represents the command and the result), and I'm passing them as json with ObjectInput(/Output)Stream.
This is the code:
Client
Socket socket = new Socket("localhost", 1111);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//get command from user
Scanner scanner = new Scanner(System.in);
System.out.println("Enter command:");
String cmd = scanner.nextLine();
Command command = new Command(cmd);
//send the command as json
String jsonCommand = new Gson().toJson(command);
out.writeObject(jsonCommand);
out.flush();
//get and print the result
String jsonCommandResult = (String) in.readObject();
CommandResult commandResult = new Gson().fromJson(jsonCommandResult, CommandResult.class);
System.out.println(commandResult.getOutput());
}
Server
ServerSocket serverSocket = new ServerSocket(1111);
Socket socket = serverSocket.accept();
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//read the command
String cmd = (String) in.readObject();
Command command = new Gson().fromJson(cmd, Command.class);
//run() method will run the command with java Process and return the result
CommandResult commandResult = command.run();
//sent the result back to the client as json
String jsonCommandResult = new Gson().toJson(commandResult);
out.writeObject(jsonCommandResult);
out.flush();
}
Now, this is working fine when I have one client.
But if I'm trying to run a second instance of the client program, while the first one is still in the loop, it hangs in the ObjectInputStream constructor. (third line)
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
As I understand from the documentation, the constructor block until the corresponding ObjectOutputStream has been created.
Creates an ObjectInputStream that reads from the specified InputStream.
A serialization stream header is read from the stream and verified.
This constructor will block until the corresponding ObjectOutputStream
has written and flushed the header.
In my case the server has not accept the new client yet, and therefore the ObjectOutputStream has not been created.
Now, what I want is to throw exception if a new client trying to connect while other client is connected to the same port.
But I can't figure it out how to check if the port is now in use before calling this constructor.
As #Kayaman proposed in the comments, I created a Runnable class handles the current client.
Then in the server, I'm looping on serverSocket.accept() and allowing only one client at the time by starting a new thread for the first client, and check whether the current client is finished his communication or not.
Here is the final Server class.
public class Server {
private static final int SERVER_READY = 1;
private static final int SERVER_BUSY = 0;
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
int port = Integer.valueOf(args[0]);
System.out.println(String.format("Starting server on port %s", port));
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server is ready");
Thread clientThread = null;
while (true) {
Socket clientSocket = serverSocket.accept();
OutputStream os = clientSocket.getOutputStream();
if (clientThread != null && clientThread.isAlive()) {
os.write(SERVER_BUSY);
continue;
}
os.write(SERVER_READY);
System.out.println(String.format("Client connected: %s", clientSocket.getInetAddress()));
clientThread = new Thread(new ClientWorker(clientSocket));
clientThread.start();
}
}
public static class ClientWorker implements Runnable {
private final Socket clientSocket;
ClientWorker(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
handleClient();
} catch (Exception e) {
e.printStackTrace();
}
}
private void handleClient() throws IOException, ClassNotFoundException {
try {
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
while (true) {
System.out.println("Waiting for command..");
String cmd = (String) in.readObject();
System.out.println(String.format("Command received:\n %s", cmd));
if (cmd.equals("exit"))
break;
Command command = new Gson().fromJson(cmd, Command.class);
CommandResult commandResult = command.run();
String jsonCommandResult = new Gson().toJson(commandResult);
System.out.println(String.format("Sending response:\n %s", jsonCommandResult));
out.writeObject(jsonCommandResult);
out.flush();
}
//in case the client connection has closed, we want to end the while loop and accept a new client
} catch (EOFException | SocketException e) {
}
System.out.println("Connection has been closed");
clientSocket.close();
System.out.println("Server is ready");
}
}
}
In the Client class, I check if the Server is ready or not.
Socket socket = new Socket(HOST, PORT);
int status = socket.getInputStream().read();
if (status != SERVER_READY)
throw new Exception(String.format("Failed to connect to server %s:%s, Server is busy", HOST, PORT));
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
....
....

java.net.SocketException : connection reset

I have read through most similar questions in Stack-overflow . But i can't find similar one.
I build one client and one server. For my client networking, i build a class which contains a socket and many relevant methods like this :
public class Connector {
private Socket socket;
private DataOutputStream output;
private DataInputStream input;
public Connector(int x) throws UnknownHostException, IOException{
socket=new Socket("localhost",x);
}
public boolean isConnected(){
return socket.isConnected();
}
public void sendInfo(String str) throws IOException{
output = new DataOutputStream(socket.getOutputStream());
output.writeUTF(str);
output.flush();
}
public String receiveInfo() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readUTF();
}
public boolean loginSuccess() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readBoolean();
}
}
and when my client runs(the server run in my IDE),
String userAccount = "VerifyAccount" + "#" + userNametf.getText() + "#" + passwordtf.getText() + "#" + i;
connector.sendInfo(userAccount);
if(connector.isConnected())
System.out.println("the connector is still connected!");
else
System.out.println("the connector is no connected!");
if(connector.loginSuccess()){
System.out.println("Log in success");
}
else;
and this is my server:
ServerSocket serverSocket = new ServerSocket(8000);
while(true){
Socket socket = serverSocket.accept();
Thread thread = new Thread(()->{
try{
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
String tempStr = input.readUTF();
System.out.println("Server receive data : "+tempStr);
String[] tempStrArray = tempStr.split("#");
if(tempStrArray[0].equals("VerifyAccount")){
if(UserVerification.isValid(tempStr.substring(14))==1){
output.writeBoolean(true);
output.flush();
}
else{}
}
else if(tempStrArray[0].equals("RegisterAccount")){}
else{}
}
catch(IOException ex){
ex.printStackTrace();
}
});
thread.start();
}
So the whole process is that the client socket connects to the server socket ,
then client send one string to the server , the server process the string , and write a boolean value back to the client , but when i call connector.LoginSuccess() , the compiler will throw an exception like this:enter image description here
You are never closing the accepted socket. You are also attempting to read a boolean that may never be sent. And, as I said in comments, isConnected() doesn't do what you think it does: it doesn't magically start returning false when the peer disconnects.

(Java) Getting two threads to communicate with each other whilst running?

I'm learning java. I'm trying to make a simple client/server chat system. What I have so far is a program where the server accepts multiple client connections by giving them each a seperate thread.
My problem now, is that I can't figure out how to get an input from one client, and then have it be sent amongst all of the clients, thus essentially have a very very simple chat mechanic. How would I go about accomplishing this? What would be the simpler way?
My code so far is here;
class Client {
public static void main(String argv[]) throws Exception {
String sentMessage; //variable for input
String receivedMessage; //variable for output
String status;
boolean running;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("127.0.0.1", 5622); //name of computer to connect with and port number to use
DataOutputStream outToServer =
new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Client Side\n");
running = true;
while(running)
{
sentMessage = inFromUser.readLine(); //user inputs text to variable 'xInput'
outToServer.writeBytes(sentMessage + '\n'); //the variable is sent to the server
status = inFromServer.readLine();
System.out.println("FROM SERVER: " + status); //display to user
}
clientSocket.close();
}
}
The server code.
class Server {
public static void main(String argv[]) throws Exception {
String clientMessage;
boolean listening = true;
int portNumber = 5622;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
new ServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
The thread that handles the client connections.
public class ServerThread extends Thread {
private Socket socket = null;
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run () {
int msgCnt = 0;
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
//something needs to go here
} catch (IOException e) {
e.printStackTrace();
}
}
If you are looking for a simple client-server communication samples then please have a look at below posts where I have described it step by step.
Multiple clients access the server concurrently
Java Server with Multiclient communication.

Cant send data from Server to client only viceverse using java

been trying to figure this problem out for about 5 hours but cant seem to see it, although all the steps are done to send data, I can only receive messages to the server, but not from server to client. I'm in the early stages of building/learning how to do a chat client program in command line. The following is the server code:
The CServer class:
public class CServer {
private static int port=2008, maxConnections=0;
private static String shutDownServer = "no";
public static void main(String[] args) throws IOException{
ServerSocket listen = new ServerSocket(port);
Socket server;
while(shutDownServer.equalsIgnoreCase("no")){
doComm connection;
System.out.println("\nWaiting for clients to connect...");
server = listen.accept(); // accept incomming connections from client
System.out.println("Client connected. Location: " + server.getInetAddress().getHostName());
connection = new doComm(server);
Thread thread = new Thread(connection);
thread.start();
}
}
public void shutDownServer(String command){
this.shutDownServer = command;
}
}
Now the doComm class that handles each client in thread:
public class doComm implements Runnable{
Socket server;
private String clientData;
public doComm(Socket server){
this.server = server;
}
public void run(){
try {
BufferedReader fromClient = new BufferedReader(new InputStreamReader(server.getInputStream()));
DataOutputStream toClient = new DataOutputStream(server.getOutputStream());
clientData = fromClient.readLine();
System.out.println("Client sent: "+clientData);
(( The problem -imo- may be either this statement: ))
toClient.writeBytes("Recieved your sentence '"+clientData+"' and more to come :)!");
//server.close();
} catch (IOException e) {
System.out.println("IOException on socket listen: " + e);
e.printStackTrace();
}
}
}
Now the client class CClient:
public class CClient {
static String address = "localhost";
static int port = 4444;
static Socket echoSocket;
public CClient(int port, String addr){
changePort(port);
changeAddr(addr);
}
public static void main(String[] args) throws IOException, UnknownHostException{
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the port to connect to: ");
int temp_port = Integer.parseInt(scan.nextLine());
System.out.println("Please enter the address of server: ");
System.out.flush();
String temp_addr = scan.nextLine();
CClient client = new CClient(temp_port,temp_addr);
PrintWriter out = null;
BufferedReader in = null;
try{
System.out.flush();
echoSocket = new Socket(address,port);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
}
catch(IOException e){
System.err.println("IOException error: " + e.getStackTrace());
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("thingy prints right after this...");
(( or here: ))
System.out.println("echo: " + in.readLine());
}
}
public void changePort(int port){
this.port=port;
}
public void changeAddr(String addr){
this.address=addr;
}
}
clientData = fromClient.readLine();
toClient.writeBytes("Recieved your sentence '"+clientData+"' and more to come :)!");
This is a very common problem whose root cause is the failure to document and specify the protocol being used for communication. Here you are receiving lines but sending bytes. If you had a protocol document, it would either specify that lines were exchanged or that arbitrary units of bytes were exchanged. That would show that one of these lines of code is wrong, and you could fix it. But without a protocol specification, you can't even tell which side is wrong.
Please, take my advice from years of painful lessons -- document a protocol before you implement. Then, if it doesn't work, you can follow this three step process:
Does the client follow the documented protocol? If not, it is broken.
Does the server follow the documented protocol? If not, it is broken.
The protocol specification is broken.
In this case, the protocol specification would document what constitutes a "message" for your protocol. It would then be each side's responsibility to send complete messages and find these message boundaries on receive. However, in your case, one piece of code expects a line terminator to mark a message boundary and the other side doesn't send one.
Is the sender wrong to omit a message boundary? Is the receiver wrong to insist on receiving one? Nobody knows because there's no specification to say what's the right thing to do.

Categories