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.
Related
Investigating the Servlets I've created a simple chat and tested it on local IP - everything works. But when I tried to test it through the real network the connection refused - java.net.ConnectException: Connection refused: connect. Is the reason in Dynamic IP which I have, or additional settings are needed? Thanks in advance!
Server:
/**
* Created by rnd on 7/4/2017.
*/
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class VerySimpleChatServer {
ArrayList clientOutputStreams;
public static void main (String[] args) {
new VerySimpleChatServer().go();
}
public void go() {
clientOutputStreams = new ArrayList();
try {
ServerSocket serverSock = new ServerSocket(5000);
while(true) {
Socket clientSocket = serverSock.accept();
Charset charset = StandardCharsets.UTF_8;
OutputStreamWriter osw = new OutputStreamWriter( clientSocket.getOutputStream(), charset );
PrintWriter writer = new PrintWriter( new BufferedWriter( osw ) );
// PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
writer.println("Welcome to the chat 7 kids.... Семеро Козлят");
writer.flush();
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start() ;
System.out.println("got a connection");
}
} catch(Exception ex) {
ex.printStackTrace();
}
} // Закрываем go
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket sock;
public ClientHandler(Socket clientSocket) {
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8);
reader = new BufferedReader(isReader);
} catch(Exception ex) {ex.printStackTrace();}
} // Закрываем конструктор
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
tellEveryone(message);
} // Закрываем while
} catch(Exception ex) {ex.printStackTrace();}
} // Закрываем run
} // Закрываем вложенный класс
public void tellEveryone(String message) {
Iterator it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch(Exception ex) {
ex.printStackTrace();
}
} // Конец цикла while
} // Закрываем tellEveryone
} // Закрываем класс
Client:
/**
* Created by rnd on 7/4/2017.
*/
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleChatClient {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;
public static void main(String[] args) {
SimpleChatClient client = new SimpleChatClient();
client.go();}
public void go(){
JFrame frame = new JFrame("Ludicrously Simple Chat Client");
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15,50);
incoming.setLineWrap(true);
incoming. setWrapStyleWord (true) ;
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming);
qScroller. setVerticalScrollBarPolicy (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ;
qScroller. setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS) ;
outgoing = new JTextField(20);
JButton sendButton = new JButton("Send") ;
sendButton.addActionListener(new SendButtonListener());
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
setUpNetworking();
Thread readerThread = new Thread(new IncomingReader());
readerThread.start();
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setSize(800,500);
frame.setVisible(true);
}
private void setUpNetworking() {
try {
sock = new Socket("178.165.87.221", 5000);
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8 );
reader = new BufferedReader(streamReader);
Charset charset = StandardCharsets.UTF_8;
OutputStreamWriter osw = new OutputStreamWriter( sock.getOutputStream(), charset );
writer = new PrintWriter( new BufferedWriter( osw ) );
// writer = new PrintWriter(sock.getOutputStream());
System.out.println("networking established");
} catch (IOException ex) {
ex.printStackTrace();}
}
public class SendButtonListener implements ActionListener {
public void actionPerformed (ActionEvent ev) {
try {
writer.println(outgoing.getText());
writer.flush();
} catch(Exception ex) {
ex.printStackTrace();
}
outgoing. setText ("") ;
outgoing.requestFocus () ;}
}
public class IncomingReader implements Runnable{
#Override
public void run() {
String message;
try{
while((message=reader.readLine())!=null ){
System.out.println("read " + message);
incoming.append(message + "\n");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
If you really have a dynamic ip, you can get yourself a freedns domain (and add a firewall exception), but most probably you're behind NAT. To make it work you need multiple things:
Still, get a freedns domain and setup automatic ip address update
hardcode the domain in the client
expose a fixed set of UDP ports by sending UDP packets to nowhere. The UDP port number on public ip usually matches the port number on your host. This part is the most important. You can check it works using public STUN/TURN servers.
Hardcode this set of ports into the client. It should try all ports on the freedns domain, until it finds a working port
The handshake packets should have a signature unique for your chat so both sides know they're trying to connect to the right software
As it appears, most NATs are Port-restricted cone NATs, that is, they drop incoming UDP packets from a peer until you send a packet to that peer. Besides, NAT UDP mappings you create by sending a packet expire in around 60 seconds, which is much less than for TCP mappings.
All this makes pure p2p messaging impossible for parties behind NAT. To join a p2p network you still need to exchange a few packets via a public server (e-mail or another Instant messaging provider). There's the library "ice4j" that can produce and parse these packets (SDP) and then create java socket wrappers for direct connections.
And even if two peers save each other's addresses to connect directly in the future, the addresses will eventually expire due to dynamic ip (usually 24h).
Sounds like either a firewall refusing the connection or a router is not port forwarding, so the request is just being refused. It doesn't sound like anything to do with having a dynamic IP.
If you are behind a router then there are settings in the router to allow port forwarding, and you might need to add a rule to your firewall. Anyway you can test by just trying to ping the server IP address from elsewhere and if that responds then even try a telnet <server ip> port to see if you can connect.
Something is getting in the way and refusing the connection!
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;
}
This code is about client and server communication in java. I can run both codes in my PC and can connect client and server. But how will I connect 2 computers as a client and server. Here are my codes for server and client as follows:
MyServer1
//code for server
import java.io.*;
import java.net.*;
public class MyServer1
{
ServerSocket ss;
Socket s;
DataInputStream dis;
DataOutputStream dos;
public MyServer1()
{
try
{
System.out.println("Server Started");
ss=new ServerSocket(10);
s=ss.accept();
System.out.println(s);
System.out.println("CLIENT CONNECTED");
dis= new DataInputStream(s.getInputStream());
dos= new DataOutputStream(s.getOutputStream());
ServerChat();
}
catch(Exception e)
{
System.out.println(e);
}
}
public static void main (String as[])
{
new MyServer1();
}
public void ServerChat() throws IOException
{
String str, s1;
do
{
str=dis.readUTF();
System.out.println("Client Message:"+str);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
s1=br.readLine();
dos.writeUTF(s1);
dos.flush();
}
while(!s1.equals("bye"));
}
}
MyClient1
//code for client
import java.io.*;
import java.net.*;
public class MyClient1
{
Socket s;
DataInputStream din;
DataOutputStream dout;
public MyClient1()
{
try
{
//s=new Socket("10.10.0.3,10");
s=new Socket("localhost",10);
System.out.println(s);
din= new DataInputStream(s.getInputStream());
dout= new DataOutputStream(s.getOutputStream());
ClientChat();
}
catch(Exception e)
{
System.out.println(e);
}
}
public void ClientChat() throws IOException
{
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
String s1;
do
{
s1=br.readLine();
dout.writeUTF(s1);
dout.flush();
System.out.println("Server Message:"+din.readUTF());
}
while(!s1.equals("stop"));
}
public static void main(String as[])
{
new MyClient1();
}
}
Client Just needs the IP of the Server.You have to find out the IP of the server and tell the client about it, like:
String serverName = "IP of server comes here"; // Indicating the place to put Server's IP
s = new Socket(serverName, 10);
Server needs no change.
You have to just enter ip of the server while creating Socket Instance.
i suggest you to follow steps
1) start hotspot in any one computer which you going to use as server
2) in second computer start wifi and connect with hotspot which we just started.
3) now ho to sharing center and click on network you connect and check detail and copy dns server ip and paste it in client program
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();
}
}
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...