I am currently working on a TCP Sockets program in Java in which two or more separate clients connect to a single server, and that server will send a message to both of these connected clients simultaneously.
I've tried to work through the code multiple times, but I can't quite seem to be able to have one message be sent to both clients.
Below is a reduced version of my entire code, condensed down to just the issue I'm having.
I've also included a video, just to save you the effort of having to copy and run my code!
[STREAMABLE LINK]
When one client is connected, I just have to write one message in the server, press send, and it shows up in the client.
When two clients are connected, I have to write two messages in the server and press send twice, and one message goes to one client and the other to the next client.
How can I make it so I only send one message from the server that goes to all clients?
I greatly appreciate any and all help.
SERVER CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Server class
class Server {
public class countLogic {
public static int client_count = 0;
}
public static void main(String[] args) {
System.out.println("[SERVER]");
ServerSocket server = null;
try {
server = new ServerSocket(1234);
server.setReuseAddress(true);
while (true) {
Socket client = server.accept();
countLogic.client_count++;
System.out.println("Client ("+countLogic.client_count+") connected: " + client.getInetAddress().getHostAddress());
ClientHandler clientSock = new ClientHandler(client);
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
PrintWriter out = null;
BufferedReader in = null;
try {
Scanner sc = new Scanner(System.in);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while (true) {
line = sc.nextLine();
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
CLIENT CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Client class
class Client {
// driver code
public static void main(String[] args)
{
System.out.println("[CLIENT 1]");
try (Socket socket = new Socket("localhost", 1234)) {
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
System.out.println("Server: "+ in.readLine());
}
// closing the scanner object
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Related
I want to send arraylist on multithreading server to client . So far i just write the conection and the clients can write and send to server msg ,the server just send back the msg to client is write somathing just sending. My main problems is how to transfer from server to client the arraylist ?
i am new on this and i dont know nothing for arralist .
code server :
import java.io.*;
import java.net.*;
import java.util.ArrayList;
// Server class
class Server {
public static void main(String[] args)
{
private ArrayList<Objects> Obj = new ArrayList<Objects>();
// file read
// String filePath = "Hotels_new.txt";
// System.out.println(Read_File( filePath ));
ServerSocket server = null;
try {
// server is listening on port 1234
server = new ServerSocket(1234);
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to server
System.out.println("New client connected" + client.getInetAddress().getHostAddress());
// create a new thread object
ClientHandler clientSock = new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static String Read_File(String filePath)
{
// Declaring object of StringBuilder class
StringBuilder builder = new StringBuilder();
// try block to check for exceptions where
// object of BufferedReader class us created
// to read filepath
try (BufferedReader buffer = new BufferedReader(
new FileReader(filePath))) {
String str;
// Condition check via buffer.readLine() method
// holding true upto that the while loop runs
while ((str = buffer.readLine()) != null) {
builder.append(str).append("\n");
}
}
// Catch block to handle the exceptions
catch (IOException e) {
// Print the line number here exception occurred
// using printStackTrace() method
e.printStackTrace();
}
// Returning a string
return builder.toString();
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
PrintWriter out = null;
BufferedReader in = null;
try {
// get the outputstream of client
out = new PrintWriter( clientSocket.getOutputStream(), true);
// get the inputstream of client
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
// writing the received message from
// client
System.out.printf(" Sent from the client: %s\n",line);
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null)
{
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
code client:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.ArrayList;
// Client class
class Client {
// driver code
public static void main(String[] args)
{
// establish a connection by providing host and port
// number
try (Socket socket = new Socket("localhost", 1234)) {
// writing to server
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
// reading from server
BufferedReader in
= new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// object of scanner class
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
// reading from user
line = sc.nextLine();
// sending the user input to server
out.println(line);
out.flush();
// displaying server reply
System.out.println("Server replied "
+ in.readLine());
}
// closing the scanner object
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
In order to send something more complex you will have to serialize it. You can choose how to do the serialization, maybe the easiest is to use ObjectOutputStream and ObjectInputStream on the server and client respectively. These can be used very similarly to the PrintWriter / BufferedReader solution you are doing now.
I had to change a few things as your example code did not compile.
Example server based on your code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
public class Server {
private static final List<Integer> myIntArray = List.of(1, 2, 3);
public static void main(String[] args) {
ServerSocket server = null;
try {
// server is listening on port 1234
server = new ServerSocket(1234);
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to server
System.out.println("New client connected" + client.getInetAddress().getHostAddress());
// create a new thread object
ClientHandler clientSock = new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(clientSocket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
while (in.readLine() != null) {
objectOutputStream.writeObject(myIntArray);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Example client:
import java.io.*;
import java.net.*;
import java.util.*;
// Client class
class Client {
// driver code
public static void main(String[] args) {
// establish a connection by providing host and port
// number
try (Socket socket = new Socket("localhost", 1234);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
// object of scanner class
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
// reading from user
line = sc.nextLine();
// sending the user input to server
out.println(line);
out.flush();
// displaying server reply
List<Integer> integers = (List<Integer>) ois.readObject();
System.out.println("server: " + integers.get(0));
}
// closing the scanner object
sc.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Keep in mind that if you are about to send your own custom types, both sides will have to know about those to be able to serialize/deserialize. Also, your classes will have to be serializable.
I had stumbled upon a dead block when doing my assignment. It's a simple server and client program.
The details of this program is as follows;
Create a server class EncryptServer that listens for incoming connections. If there is a connection, accept it and create a thread EncryptServerSession to handle the input and output stream.
Create a thread class EncryptServerSession that takes in the input and output stream from the server class and process it.
Create a client class EncryptClient that connects to the server class and takes output stream from EncryptServerSession through EncryptServer.
Somehow the while true loop of the EncryptClient class is not working. I cannot seem to get into the loop. Is something wrong with my code? Thanks in advance.
EncryptServer
import java.net.*;
import java.io.*;
public class EncryptServer
{
public EncryptServer() throws IOException
{
ServerSocket serverSocket = new ServerSocket(1122);
System.out.println("Server started.");
while (true)
{
Socket conSocket = serverSocket.accept();
System.out.println("Client connected from " +
conSocket.getLocalAddress().getHostName());
Thread session = new
EncryptServerSession(conSocket.getInputStream(),
conSocket.getOutputStream());
session.start();
}
}
public static void main(String[] args)
{
try
{
EncryptServer server = new EncryptServer();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptServerSession
import java.net.*;
import java.io.*;
public class EncryptServerSession extends Thread
{
BufferedReader in;
Writer out;
public EncryptServerSession(InputStream inStream, OutputStream outStream)
{
Reader read = new InputStreamReader(inStream);
in = new BufferedReader(read);
out = new OutputStreamWriter(outStream);
}
public void strEncrypt()
{
try
{
String message = in.readLine();
out.write(message);
out.flush();
}
catch (Exception e)
{
}
}
public void run()
{
try
{
//System.out.println(in.readLine());
out.write("Please enter the message to be encrypted: ");
out.flush();
//strEncrypt();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptClient
import java.net.*;
import java.io.*;
public class EncryptClient
{
BufferedReader input, userTerm;
Writer output;
String line;
public EncryptClient() throws IOException
{
Socket clientSocket = new Socket("localhost", 1122);
Reader read = new InputStreamReader(clientSocket.getInputStream());
input = new BufferedReader(read);
userTerm = new BufferedReader(new InputStreamReader(System.in));
output = new OutputStreamWriter(clientSocket.getOutputStream());
/////////////// Somehow I cannot get into this loop, why? //////////
while (true)
{
System.out.println("test ");
System.out.println(input.readLine());
System.out.println("Enter message to be encrypted: ");
output.write(userTerm.readLine());
output.flush();
}
/////////////// Somehow I cannot get into this loop, why? //////////
}
public static void main(String[] args)
{
try
{
EncryptClient client = new EncryptClient();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
As I understand, you are trying to send a message to a server, do some logic, then send it back to the client. The above code seems to run well on my side. Here's what I've done:
run EncryptServer first. I expect this is the issue you are facing. or maybe your firewall isn't letting you listen on sockets.
in EncryptServerSession, You are reading lines but you aren't writing lines. either close the stream or write a new line after you finish.
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
} finally {
try {
out.close();
} catch (IOException e) {
}
}
OR
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages
Can anyone see what i might be doing wrong here please?
Thanks
public class Sender {
Socket server = null;
DataInputStream inp = null;
PrintStream outp = null;
public Sender(){
server = new Socket("127.0.0.1" , 3456);
outp = new PrintStream(server.getOutputStream());
}
private void connectAndSendToServer(String message) {
outp = new PrintStream(server.getOutputStream());
outp.print(message + "\n");
outp.flush();
}
}
Receiver class
public class Receive{
public String receiveMessage(int port) {
String message= null;
ServerSocket listener = null;
Socket client = null;
try{
listener = new ServerSocket(port);
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
return br.readLine();
}
...
finally{
try {
if(client!=null && listener!=null){
client.close();
listener.close();
}
}
catch (IOException e) {
}
}
return message;
}
}
This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.
This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.
Socket socket = serverSocket.accept();
ClientThread thread = new ClientThread(socket);
class ClientThread extends Thread {
Socket socket;
public void run() {
while (!closed) {
String line = reader.readLine();
...
}
}
You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.
You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):
while(< condition met >) {
try {
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = br.readLine();
//do something with str
} finally {
//close client socket
}
}
Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.
Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for your Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}
I've just started with this section of the tutorial. I only have a basic understanding of what ports are, etc.
I tried to run this code:
import java.io.*;
import java.net.*;
public class EchoClient {
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket("taranis", 7);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: taranis.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: taranis.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
}
"Don't know about host: taranis.
Java Result: 1"
Is the error catch I get. From my limited understanding; is the echo-server something which exists on my machine? If that's the case, what do I need to do to get this running? Or am I way off?
Also why have they chosen "taranis" as a parameter?
Ive also replaced "taranis" with "localhost" to see what happened.
It ended up catching an IOException this time.
EDIT: So I've found that the echo server is disabled by default in win7 and have activated it. However I cant even connect to it on telnet. I think I may just be in over my head. I've also tried the sockets you have recommended with no success.
From the same tutorial:
... The Socket constructor used here requires the name of the machine and the port number to which you want to connect. The example program uses the host name taranis. This is the name of a hypothetical machine on our local network. When you type in and run this program on your machine, change the host name to the name of a machine on your network. Make sure that the name you use is the fully qualified IP name of the machine to which you want to connect. The second argument is the port number. Port number 7 is the port on which the Echo server listens.`
In any case, you will probably want to change taranis to "localhost" and make sure an echo service is running on your machine. If it's not, you could use something like the following code to simulate an echo server.
import java.net.Socket;
import java.util.Formatter;
import java.util.Scanner;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EchoServer {
public static void main(String[] args) {
try {
new EchoServer(INSERTPORT).execute();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
private ServerSocket serverSocket;
private int port;
private ArrayList<Client> clientList;
private ExecutorService clientRunner;
public EchoServer(int port) throws IOException {
this.port = port;
serverSocket = new ServerSocket(port);
clientRunner = Executors.newCachedThreadPool();
clientList = new ArrayList<>();
}
public void sendMessageToAll(String message) {
for (Client c : clientList) {
c.displayMessage(message);
}
}
public void execute() throws IOException {
while (true) {
clientList.add(new Client(serverSocket.accept(), this));
clientRunner.execute(clientList.get(clientList.size()-1));
}
}
private class Client implements Runnable {
private Socket clientSocket;
private Scanner input;
private Formatter output;
public Client(Socket s) throws IOException {
clientSocket = s;
input = new Scanner(clientSocket.getInputStream());
output = new Formatter(clientSocket.getOutputStream());
}
public void displayMessage(String s) {
output.format(s + "\n");
output.flush();
}
#Override
public void run() {
while(clientSocket.isConnected()) {
if(input.hasNextLine()) {
sendMessageToAll(input.nextLine());
}
}
}
}
}
Edit: Just for completeness, as you mentioned some problems running the code, you run the server (this code) and leave it running in the background, then run the client (the code you posted). I tested it, works fine.
Try this,
Use the loopback address of 127.0.0.1 instead of taranis.
Use port higher than 1024, something like 4444, 8333 etc....
I am also adding my code that i used to learn Client Server Commnu
Client Side Code:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Side Code:
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
hi i writ acode for client and for server and now i want to deliver the message between clint one to clint two and i dont succees to do this on server side i want to construct array for name and id and after i send message from the client side i can choose where or Which name the server deliver the message pleas help me to writ this
so this is the clint side
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
System.out.println("Say something:");
String userInput = readerFromCommandLine.readLine();
writer.println(userInput);
writer.flush();
String input = reader.readLine();
System.out.println("Got from server: "+input);
if (userInput.equalsIgnoreCase("bye")) {
break;
}
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
so now my code shuold by look like this ?
becaus i not yet can send from one client to client two
import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class server {
public static void main(String[] args) {
ArrayList<Channel> my_clients = new ArrayList<Channel>();
ServerSocket ss = null;
try {
ss = new ServerSocket(7777);
while (true) {
//wait for a new client call - once got it, get the socket for
//that channel
System.out.println("Waiting for an incoming call");
Socket client = ss.accept();
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
//once the call has started read the client data
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
//my_client.writer("HELLO!");
}
}
//System.out.println("Accepted a new call");
//new Channel(client).start();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (ss != null) {
try {
ss.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
public static class Channel extends Thread {
private static int clientIndex = 0;
private int index;
private Socket socket = null;
public Channel(Socket socket) {
clientIndex++;
index = clientIndex;
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true) {
String input = reader.readLine();
System.out.println("Got from client "+index+": "+input);
//bye bye
if (input.equalsIgnoreCase("bye")) {
break;
}
writer.println("Gotcha");
writer.flush();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
}
String userInput = readerFromCommandLine.readLine();
BufferedReader.readLine() is a problem here. It is going to block your thread until input is received. This means communication can only ever go in one direction at a time, and can potentially get totally blocked if both clients are waiting.
DataFetcher can fix this problem; you can use it to listen in a separate Thread
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
You half way there.
You created a Threaded Server were each connection from a client opens a thread. This thread then loops and waits for messages.
Think of these threads as you connected clients with their own objects / properties and their streams to write to and read from them.
So each time a clients connections you want to create their thread add it to some kind of list and start their thread. For example:
At the top of the class
List<Channel> my_clients = new List<Channel>();
In your while loop
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
Then when you want to send a message to a certain clients. You can loop all the Threads and look for one that has some kind of name or Unique Indentifier. For example:
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
my_client.write("HELLO!");
}
}
or in the same breath you could send a message to all your clients (Broadcast):
for(Channel my_client : my_clients) {
my_client.write("HELLO!");
}
remember to remove the clients when they disconnect too!
// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
my_clients.remove(this);
}
Note this expects that you some how authenticate and know the name of your client or supply them a UID which you reference when you are instructed to sent them something. And that the Channel class has the Write Method for connivance.
Hope that Help!