How would I create Sockets on demand in Java? - java

I am making a client to client chatting application in Java and I wanted to know how I could create Sockets on demand. More specifically, I wanted to know if there is any method which checks whether there is an incoming connection. Using that I could have two methods running simultaneously together with Threads with one method waiting for a connection while the other handles the server (messages being sent). Is this a fine strategy or should I use a different technique?
What if I used a Socket Array and added a new Socket to it with each connection?
Would the array however cause a problem when referencing to Sockets later on?
The if has a && with nothing as I want to add a method there which will help me check whether there is an incoming connection or not.
import java.util.*;
import java.io.*;
import java.net.*;
public class Server {
public static ServerSocket SSock;
public static Socket Sock;
public static DataInputStream dis;
public static DataOutputStream dos;
public static PrintWriter pw;
public static BufferedReader br;
public static Socket[] wow;
public int counter = 0;
public int port = 2500;
public Scanner input = new Scanner(System.in);
public static void main(String[] args) throws IOException{
SSock = new ServerSocket();
Sock = SSock.accept();
dis = new DataInputStream(Sock.getInputStream());
dos = new DataOutputStream(Sock.getOutputStream());
pw = new PrintWriter(dos, true);
br = new BufferedReader(new InputStreamReader(dis));
Server s = new Server();
Thread t1 = new Thread(s.new connection());
Thread t2 = new Thread(s.new server());
t1.start();
t2.start();
}
public class connection implements Runnable {
public void run() {
try {
Thread.sleep(200);
} catch (Exception e) {
//NOTHING!! MWAH MWAH MWAH
//Sigh. I'll add something here later...
}
if ( && Sock.isConnected()) {
}
}
}
public class server implements Runnable{
public void run() {
}
}
}

I think you have somehow misunderstood the concept of TCP sockets. When you try to initiate a connection to remote server it does not “create demand;” the server has to listen on the socket before you initiate the request, otherwise you will only get a “connection refused” error.
In Java, ServerSocket.accept() handles all that for you: it listens for incoming connections and as soon as a connection has been established, it returns you the Socket that you use for all further communication on this particular connection.

I figured it out I have to make a method which returns a socket.
public Socket s (Socket so) { //When I add a Socket to an arraylist, I call this method
//edit properties
return so;
}

Related

Java Server/Client for two computers

I am creating a chat between multiple computers, but i cannot find how to connect a socket to a serverSocket that is not in the client's computer.
P.S. I am new of socket programming.
This is server
package chat;
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
public List<String> names = new ArrayList<String>();
public HashMap<String, Socket> sockets = new HashMap<String, Socket>();
public HashMap<String, BufferedReader> inputs = new HashMap<String, BufferedReader>();
public HashMap<String, PrintWriter> outputs = new HashMap<String, PrintWriter>();
public void start() throws IOException {
int port = 2019;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server started");
while(true) {
System.out.println("\nLooking for new channels in the subspace.");
Socket socket = serverSocket.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
System.out.println("Someone connected.");
new Thread() {
public void run() {
//various input/output operations
}
}.start();
}
}
public static void main(String[] args) throws IOException {
Server server = new Server();
server.start();
}
}
this is Client
package chat;
import java.io.*;
import java.net.*;
public class Client {
public Socket socket;
public BufferedReader input;
public PrintWriter output;
public void start() throws IOException {
String host = "192.168.1.4 / 127.0.0.1 / computer's global ip";
int port = 2019;
socket = new Socket(host, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
System.out.println("Successfully established connection to " + host + ":" + port);
new Thread() {
public void run() {
//output operations
}
}.start();
new Thread() {
public void run() {
//input operations
}
}.start();
}
public static void main(String[] args) throws IOException {
Client client = new Client();
client.start();
}
}
Now, the problem is that this works when server and client are on the same pc.
I sent to my other computer a copy of the client file but when i insert the ip of the server's computer (192.168.1.4) nothing happens.
Both computers are connected to the same WI-FI.
Another question is: how to connect 2 computers without the same WI-FI?
After 2 years I have enought knowledge about this, so I will answer to help anyone with similar problems.
The problem is not Java, that client-server code should work.
If it doesn't, the problem is the network: if the server is connected to a router (which usually is) then there is no way to access it directly (it doesn't have a public IP itself, but only a local IP; the public IP used is the router's IP). So you need to connect to do "port forwarding", that is telling your router that any connection to a given port has to be sent to 192.168.1."x" local IP. This is handheld by the NAT.
TLDR
Learn about port forwarding and public/private IPs.

Can a client program have a server socket to communicate to other client programs?

I am trying to implement a multithreaded socket program that simulates five computer and a controller communicating with each other via sockets. The controller has a server socket that accepts incoming sockets (from computers). Once it reaches the max capacity of the system (let's say five), then it will send out a start message to those computers using threads that was created when accepting incoming sockets.
When each computer receives the Start message from the controller, I want to be able for each computer to communicate with other computers (without relying on controller (relaying messages from computer to controller to computer). What I thought would work is having each computer instantiate a server socket so that it can accept incoming sockets from computers. And also instantiate another client socket so that other server sockets from different computers can accept it.
I know this may sound pretty confusing, but basically I want to use a server socket on each client program (computer) so that it can listen to other clients (computer) without relying on the controller.
Is this possible? Can I instantiate each client program (computer) a server socket so that it can listen to other computers? Does it need a different IP address and/or port number from the controller's server socket? Do I need to instantiate x amount of sockets for x amount of computers?
Maybe my Java code can make sense of this.
Controller.java
package timetableexchange;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Controller {
final int MAX_SYSTEMS = 2;
static ArrayList<ServerConnection> conns = new ArrayList<ServerConnection>(); // connections to computer
static int finishedCount = 0; // number of finished computers
ServerSocket ss; // server socket
public static void main(String[] args) throws IOException {
// Instantiate controller
new Controller(8000);
}
public Controller(int port) throws IOException {
// Instantiate server socket
ss = new ServerSocket(8000);
int i = 0;
// Listen and accept clients (1 for testing)
while (i < MAX_SYSTEMS) {
Socket s = ss.accept();
// add to list
ServerConnection conn = new ServerConnection(i++, s);
conns.add(conn);
}
// start server connection thread
for (i = 0; i < conns.size(); ++i) {
conns.get(i).start();
}
ss.close();
}
// Thread for communicating between controller and computer
private class ServerConnection extends Thread {
Socket socket;
BufferedReader in;
PrintWriter out;
int identifier;
// constructor
public ServerConnection(int i, Socket s) throws IOException {
this.identifier = i;
this.socket = s;
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Client Connected");
}
#Override
public void run() {
System.out.println("ServerConnection started");
// send ID to computers
sendAll(identifier + "");
// send Start message to computers
sendAll("Start");
// Check if a computer sent back a Finish message
// If all computers are finished, then send out Tear Down message.
while (true) {
try {
String clientInput = in.readLine();
if (clientInput.equals("Finish")) {
finishedCount += 1;
if (finishedCount == conns.size()) {
sendAll("Tear Down");
}
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
private void sendAll(String text) {
for (int i = 0; i < conns.size(); ++i) {
ServerConnection conn = conns.get(i);
conn.out.println(text);
}
}
}
}
Computer.java
package timetableexchange;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Vector;
public class Computer {
final int MAX_SYSTEMS = 2;
int identifier; // Computer ID
int eventCount; // Number of Generated Events
ArrayList<Socket> sockets = new ArrayList<Socket>(); // List of (client) sockets
Vector<Integer> timestamp = new Vector<Integer>(); // Time-stamp vector
Socket socketToServer; // Socket to Connect to Controller
BufferedReader inputFromServer; // Input Stream from Controller
PrintWriter outputToServer; // Output Stream to Controller
String textFromServer; // String sent from Controller
ServerSocket ss; // Server Socket to communicate with other clients (computers)
Socket socketToClient; // Socket to Connect to Computer
BufferedReader inputFromClient; // Input Stream from Computer
PrintWriter outputToClient; // Output Stream to Computer
public static void main(String[] args) throws IOException {
// Instantiate Computer
new Computer("127.0.0.1", 8000);
}
// Constructor
public Computer(String hostname, int port) throws IOException {
// Instantiate Socket (to Controller) and Streams (to Controller)
socketToServer = new Socket(hostname, port);
inputFromServer = new BufferedReader(new InputStreamReader(socketToServer.getInputStream()));
outputToServer = new PrintWriter(socketToServer.getOutputStream(), true);
// Check if Controller sent the computer its ID
while (true) {
try {
textFromServer = inputFromServer.readLine();
// set identifier
identifier = Integer.parseInt(textFromServer);
System.out.println(identifier);
break; // break loop
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
// Check if Controller sent the start message
while (true) {
textFromServer = inputFromServer.readLine();
if (textFromServer.equals("Start"))
System.out.println("Start message received");
break; // break loop
}
// Instantiate Server Socket (for Clients)
ss = new ServerSocket(port + identifier + 1);
// Instantiate Client Socket for Other Clients to Hear
socketToClient = new Socket();
inputFromClient = new BufferedReader(new InputStreamReader(socketToClient.getInputStream()));
outputToClient = new PrintWriter(socketToClient.getOutputStream());
// listen to server socket and add accepted socket to list
for (int i = 0; i < MAX_SYSTEMS - 1; ++i) {
Socket s = ss.accept();
System.out.println("Client accepted");
sockets.add(s);
}
Thread readEvent = new Thread(new Runnable() {
#Override
public void run() {
/**
* Read from input stream
* Read the vector inside the input stream
* Compare vectors and choose the largest integer (synchronized)
* Add 1 to the corresponding socket. (synchronized)
*/
}
});
Thread writeEvent = new Thread(new Runnable() {
#Override
public void run() {
/**
* Generate random number between 0 and 4.
* If zero, then add 1 to its own socket in vector.
* Else, send vector to random socket via output stream
*/
}
});
readEvent.start();
writeEvent.start();
}
}
I appreciate the help!
In short:
Is this possible?
Yes - why not?
Can I instantiate each client program (computer) a server socket so
that it can listen to other computers?
Yes - you can do whatever you want or need
Does it need a different IP address and/or port number from the
controller's server socket?
IP address belongs to "physical computer"/hetwork interface and it does not matter to what you are trying to do - all can run on one computer and all can run on the same IP address (e.g. 127.0.0.1). You have to have dedicated ports for each Server socket you are about to open, and your client sockets must know IP and port numbers to communicate with.
for client socket you do not need to care about neither IP nor port number.
Do I need to instantiate x amount of sockets for x amount of
computers?
Question does very little sense ro me - it is your design decision how many Server sockets you need to instantiate - one Server socket for one port, that's it.

Able to write the data successfully but not able to read the data from the server

I have two classes server and client. I am running both the server and the client on the intelliji. I am able to write the data to the Json file on the server but when it comes to reading the data, I am not able to read it. My application is not responding when I am trying to read the data. I am new to Socket Programming please help me.
Here is the code on the client side
import java.io.*;
import java.net.Socket;
public class Client {
public String readDataFromServer(Socket socket) throws IOException {
InputStreamReader inputStreamReader = new
InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
return bufferedReader.readLine();
}
public void writeDataToServer(String obj) throws IOException {
Socket socket = new Socket("localhost", 1299);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(socket.getOutputStream());
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.write(obj);
printWriter.flush();
printWriter.close();
}
}
Here is the code on the server side
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
static void writeJson (String str) throws IOException {
FileWriter pw = null;
try {
pw = new FileWriter("MYJSON.json", true);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
pw.write(str + '\n');
pw.flush();
try {
} catch (Exception E) {
E.printStackTrace();
}
pw.close();
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1299);
Socket socket = serverSocket.accept();
InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = bufferedReader.readLine();
writeJson(str);
FileReader fileReader = new FileReader("MYJSON.json");
BufferedReader buff = new BufferedReader(fileReader);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(socket.getOutputStream());
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.write(buff.readLine());
printWriter.flush();
}
}
I have another class called display controller which is calling the method which is calling the method by passing the socket object. Here is the piece of code from this class.
Client client = new Client();
button1.setOnAction(e-> {
try {
String str;
while ((str = client.readDataFromServer(socket)) != null) {
Object obj = null;
try {
obj = jsonParser.parse(str);
What I am doing wrong here? How do I fix it?
Thank you
There's a couple of issues in your code.
The main one is in the main method of the Server class. Your server only accepts one connection. That connection writes and reads the json file and then your main method ends. If your main program ends, then the server is gone. This means that the first client that connects will work and write to the file, but any subsequent connections will not connect because there's no server accepting connections anymore. Typical servers run indefinitely by using a while loop with true as the condition.
Example Structure of a server without threads:
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by referencing
// the connection.
private class ClientInstanceOnTheServer {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.run();
}
} finally {
serverSocket.close();
}
}
}
Example Structure of a server with Threads:
NOTE: The code below is not to represent a complete solution with threads, but rather an example to explain how a server works.
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by
// the connection and it runs in a separate thread to not block
// the main method thread on this server.
private class ClientInstanceOnTheServer extends Thread {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// and it should use a separate thread for each client to not block the main method thread.
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.start(); // this will execute the run method in ClientInstanceOnTheServer class.
}
} finally {
serverSocket.close();
}
}
}
Your server is always doing both, writing and reading the json file, regardless of what the client wants. The server should somehow allow the client to communicate what it wants to do, and then it executes only what the client asked for. If we use the skeleton code above, this logic would go in the method logicToServeAClient of the ClientInstanceOnTheServer class. The server and client use the socket object's input and output streams to communicate with each other. The server and client need to agree beforehand on which commands/operations the client needs and the server is willing to serve. In your case, it would be READ and WRITE. Then you create a contract (Protocol) between the client and server on how to send these commands to the server and how the server will respond to the client for each command.
Example of a protocol:
// client sends READ to server
// client waits for respond from server
// server read json file and send it to the client
// client sends WRITE to server
// server then waits for the client to send the string to write.
// Once it receives the string, it writes it to the json file.
All of this is achievable using the socket's input and output streams
It's important to distinguish the difference between the Client and the ClientInstanceOnTheServer classes. Client is your Client class that connects to the server and ClientInstanceOnTheServer holds the connection and also runs the server code that serves the commands requested by the Client class. In the protocol above, whenever client is mentioned, is referring to the Client class. Whenever the server is mentioned is referring to the ClientInstanceOnTheServer class.
You can find more examples on google, like: http://cs.lmu.edu/~ray/notes/javanetexamples/. However, this should set you up on a path to fix your issue.
Cheers

TCP socket connection

I'm new to the network communication and I'm trying to build client-server application.
protected void init(){
Server myServer = new Server();
Client myClient = new Client();
}
That's my Client class:
public class Client {
public Client() {
init();
}
private void init() {
Socket echoSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
DataInputStream stdIn = new DataInputStream(System.in);
try {
echoSocket = new Socket("localhost", 1234);
os = new DataOutputStream(echoSocket.getOutputStream());
is = new DataInputStream(echoSocket.getInputStream());
os.writeInt(stdIn.readInt());
echoSocket.getOutputStream().close();
echoSocket.getInputStream().close();
echoSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And that's server:
public class Server {
public Server() {
init();
}
private void init() {
try {
boolean run = true;
ServerSocket ss = new ServerSocket(1234);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(dis.readInt());
s.getInputStream().close();
s.getOutputStream().close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
First of all:
Can I initialize client and server simply like i did? new Server() and new Client()?
Question 2:
Is it important what i initialize at first? client or server?
Question 3:
When i compile this code with client first initialized, i become Connection refused: connect. I know it means that there is no listening socket running on the port you are trying to connect to. That's why server must go first, i think. Is it so? can i fix it using setSoTimeout and how?
Question 4:
When i compile it with server and then client, output is nothing. And i think it has nothing to do with client, because if i try to print "1", for example, it doesn't work either. I think it just waits for the client and does nothing that goes after. How can i fix this? maybe setSoTimeout goes here too?
You can't have both client and server in the same thread.
As you already have observed, the server accepts the connection and tries to read something. It doesn't know that the client is running in the very same thread.
Either make a multi-threaded application, where client and server have their own thread. Or make two prgrams that run independently of each other. The latter would be also the "normal case".
Make two different projects, first run server than client.
Server will write on console "Server started" than run client it will ask your name, type your name press ok . Your name will be sent to server and server will reply saying hello to you.
Here is server code
import java.net.*;
import java.io.*;
import javax.swing.*;
public class Server {
public static void main(String[] args) {
try{
ServerSocket ss= new ServerSocket(2224);
System.out.println("Serever started");
while(true)
{
Socket s=ss.accept();
InputStream is=s.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os);
String name=br.readLine();
String message="Hello "+name+"from server";
pw.println(message);
pw.flush();
}
}
catch(Exception exp)
{
System.out.println("Excepttion occured");
}
}
}
Here is client code
import java.net.*;
import java.io.*;
import java.util.Scanner;
import javax.swing.*;
public class Client {
public static void main(String[] args) throws IOException {
Socket s=new Socket("localhost",2224);
InputStream is=s.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os,true);
String message = JOptionPane.showInputDialog("Give your name");
pw.println(message);
pw.flush();
String servermessage = br.readLine();
JOptionPane.showMessageDialog(null, servermessage);
s.close();
}
}

Multiple client to server communication program in Java

I wrote a server-client communication program and it worked well.
Client module
import java.io.*;
import java.net.*;
class Client {
public static void main(String argv[]) throws Exception {
String sentence;
String modifiedSentence;
while(true){
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("myname.domain.com", 2343);
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Ready");
sentence = in.readLine();
out.writeBytes(sentence + '\n');
modifiedSentence = in.readLine();
System.out.println(modifiedSentence);
}
clientSocket.close();
}
}
Server module
import java.net.*;
public class Server {
public static void main(String args[]) throws Exception {
String clientSentence;
String cap_Sentence;
ServerSocket my_Socket = new ServerSocket(2343);
while(true) {
Socket connectionSocket = my_Socket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream out = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = in.readLine();
cap_Sentence = "Raceived:" + clientSentence + '\n';
out.writeBytes(cap_Sentence);
}
}
}
The above is the code for a single client - server communication, now I want multiple client to interact with that server. I googled for it and found that it can be done with the use of a thread for each single client to talk to the server, but since I am a beginner I don't know exactly how to implement. So somebody please tell me how to do or give me some idea about it.
MainServer class
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listeningSocket = true;
try {
serverSocket = new ServerSocket(2343);
} catch (IOException e) {
System.err.println("Could not listen on port: 2343");
}
while(listeningSocket){
Socket clientSocket = serverSocket.accept();
MiniServer mini = new MiniServer(clientSocket);
mini.start();
}
serverSocket.close();
}
}
Helper Class
public class MiniServer extends Thread{
private Socket socket = null;
public MiniServer(Socket socket) {
super("MiniServer");
this.socket = socket;
}
public void run(){
//Read input and process here
}
//implement your methods here
}
You want to look into Java concurrency. That's the concept of one Java program doing multiple things at once. At a high level you will be taking your while(true) { //... } block and running it as part of the run() method of a class implementing Runnable. You'll create instances of Thread that invoke that run() method, probably one per client you expect.
For a really good, deep understanding of all that Java offers when it comes to concurrency, check out Java Concurrency in Practice.
Well, when I do something like that, I implement a listener that manages the server side, so when a client (the client won't probably need changes) connects, the server launch one thread to work with that client.
while (!stop)
{
socket = serverSocket.accept();
HiloSocket hiloSocket = new HiloSocket(socket, this);
hiloSocket.start();
}
Of course, HiloSocket extends Thread and it has the logic behind to manage the client...

Categories

Resources