I am writing a server-client program. It is like a simple console chat room. I use server thread to handle multiple clients. It works well if I put the Scanner inside the client constructor.(This part is commented) But, I want to move the Scanner part which requests input from user to the main. I got socket close error.I don't know what the problem is. How can I use send function to send data in main?
Client:
public class GameClient {
private Socket socket;
private String serverIP;
private OutputStreamWriter writer;
private BufferedReader reader;
public GameClient(String host){
this.serverIP = host;
try{
//Connect to server
socket = new Socket(InetAddress.getByName(serverIP), 1234);
writer = new OutputStreamWriter(this.socket.getOutputStream(), "UTF-8");
reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), "UTF-8"));
//Start a new thread for reading from server
new Thread(new GameClientReader(socket)).start();
Scanner scanner = new Scanner(System.in);
System.out.println("Write something: ");
String str = "";
// while((str = scanner.nextLine()) != null){
// writer.write(str);
// writer.write('\n');
// writer.flush();
// System.out.println("Write something: ");
// }
}catch(IOException e){
System.out.println("Client failed to connect!");
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void send(JSONObject json){
try{
String message = json.toJSONString();
writer.write(message);
writer.write('\n');
writer.flush();
}catch(IOException e){
e.printStackTrace();
}
}
public void send(String msg){
try {
writer.write(msg);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
GameClient client = new GameClient("127.0.0.1");
Scanner scanner = new Scanner(System.in);
System.out.println("Write something: ");
String str = "";
while((str = scanner.nextLine()) != null){
client.send(str);
System.out.println("Write something: ");
}
}
}
You close Socket in finally block of GameClient constructor, and then call method send which calls writer.write(msg); that uses instance of Socket
Related
so i've been making a simple chat, than has a server and a bunch of clients connected to them. On the client side i have class ConnectionManager to manage creating socket and such. Here is it's core method:
public class ConnectionManager {
private Socket socket;
private BufferedReader reader;
private PrintWriter writer;
public ConnectionManager(String URL, int port){
tryConnectToServer(URL, port);
}
public BufferedReader getReader() {
return reader;
}
public PrintWriter getWriter() {
return writer;
}
private void tryConnectToServer(String ip, int servSocket) {
try{
socket = new Socket(ip, servSocket);
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
}
catch (IOException ex){
System.out.println("Unable to connect to specified server. Code pink");
ex.printStackTrace();
}
}
Connection Manager object is a part of ChatGUI. ChatGUI's fields writer and reader are obtained and set from CM in order to pass writer along with ChatGUI's JTextField (msgInput) to SendButtonListener:
private void addSendButton() {
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonActionListener(writer, msgInput));
panel.add(sendButton);
panel.add(this.msgArea);
}
Then, actionPerformed method does:
public class SendButtonActionListener implements ActionListener{
private PrintWriter writer;
private JTextField msgInput;
public SendButtonActionListener(PrintWriter pr, JTextField mi){
writer = pr;
msgInput = mi;
}
public void actionPerformed(ActionEvent event){
writer.println(msgInput.getText());
System.out.println("Sending: " + msgInput.getText());
flushMessageInputField();
}
private void flushMessageInputField(){
msgInput.setText("");
}
}
On the server side on the other hand i've got this:
try{
this.servSocket = new ServerSocket(port);
System.out.println("Server socket established");
}
catch (IOException ex){
System.out.println("Unable to establish server socket. Code pink \n");
ex.printStackTrace();
}
And after the above comes this:
public void waitForClients(){
System.out.println("The gates has been opened...");
while (true){
try {
Socket client = servSocket.accept();
processClient(client);
}
catch (IOException ex){
ex.printStackTrace();
}
}
}
private void processClient(Socket client){
writers.add(getClientWriter(client));
startUpdateFrom(client);
System.out.println("New client connected: " + client.getPort());
}
private PrintWriter getClientWriter(Socket client){
try{
return new PrintWriter(client.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
return null;
}
And finally, a new thread starts to listen to any new messages from that client:
private void startUpdateFrom(Socket client){
new Thread(
new WaitAndSendToAllFrom(client))
.start();
}
Which is:
public class WaitAndSendToAllFrom implements Runnable{
BufferedReader reader;
public WaitAndSendToAllFrom(Socket clientSocket){
try{
reader = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
}
catch (IOException ex){
ex.printStackTrace();
}
}
public void run(){
try{
String message;
System.out.println("Thread: waiting for messages to send...");
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
}
catch (IOException ex){
ex.printStackTrace();
}
}
private void sendToAll(String message){
List<PrintWriter> writers = ServerClientConnector.getWriters();
for (PrintWriter pr : writers){
pr.println(message + "\n");
pr.flush();
}
}
}
The cycle gets to the "Thread: waiting for messages to send...", but not any further, reader.readLine() returns null (checked with a sysout :) ). I was trying to debug it, but i'm not so experienced in programing so much, especially debugging two separate codes working with each other. I've been looking at this for 3 days, and i'm seriously stuck here.
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
This makes no sense. You read one line and then keep testing. It for null in a loop in which it can never change.
A proper way to write this is:
while ((message = reader.readLine()) != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
So this is the first Server-Client I am trying to 'setup' but it does not work as I want it to. Here is What I want:
The Client to do: (see comments in the code for the Client)
A 'user input' should be read by the Client
Send the 'user input' to the server
receive back something from the server
The server to do: (See the comments in the code for Server)
receive the 'user input' that read by the client
Do something with the 'user input'
Send what was done in (2), back to the client.
It is not working the only right thing it is doing is that it receives the input from the 'user', that is it:
public class Cli {
BufferedReader in;
PrintWriter out;
Socket s;
public Cli(int port){
try {
s = new Socket("127.0.0.1", port);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader
(s.getInputStream()));
} catch (UnknownHostException e) {
System.out.print("fel");
} catch (IOException e) {
System.out.print("fel");
}
}
public void startaClient(){
BufferedReader stdIn = new BufferedReader (new InputStreamReader(System.in));
try {
while(true){
String userInput = stdIn.readLine();// get the user input (1)
System.out.print("from user: " + userInput);
out.write(userInput); // sends to server (2)
System.out.println(in.readLine()); // receive from server(3)
}
} catch (Exception e){
System.out.println("fel1");
}
}
public static void main(String[] args){
Cli c=new Cli(4002);
c.startaClient();
}
Here is the code for the Server:
public class Ser {
ServerSocket s;
public Ser()throws Exception{
s = new ServerSocket(4002);
}
public void startaServern()throws Exception {
while (true) {
Socket socket = s.accept(); //waits for new clients, acceptera inkommande förfrågan
Trad t = new Trad(socket);
t.start();
}
}
public static void main(String[] args)throws Exception{
Ser b = new Ser();
b.startaServern();
}
}
public class Trad extends Thread {
Socket socket;
BufferedReader in;
PrintWriter out;
public Trad(Socket s){
socket=s;
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //
out=new PrintWriter(socket.getOutputStream(),true);
}catch(Exception e){System.out.println("fel");}
}
public void run(){
while(true){
try{
String theInput = in.readLine(); //read, receive message from client (1)
String res = theInput+"blabla"; // do something with the message from the client (2)
out.write(res); // send it back to the client (3)
} catch(Exception e) {
System.out.println("fel1");
}
}
}
}
When you do readLine() it will read a line i.e. until it reaches a new line.
Unless you send a new line it will wait forever. I suggest you send a newline so the reader knows the line has ended.
Since you are using a PrintWriter the simplest solution is to use
out.println(res);
instead of out.write(res);
My code just do a simple task send a text from client's console to server and receive a reply. But my code doesn't work though. I keep sending text to server and no reply sending back. I have done a several example that plus 2 number given from client. I do this the same way but i can't figure out what is the problem.
Server:
public class Server {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(8);
Socket client = server.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter outToClient = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String in = inFromClient.readLine(),out;
while(in!=null){
out = in+" from server";
outToClient.write(out);
outToClient.newLine();
outToClient.flush();
}
inFromClient.close();
outToClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Client:
public class Client {
public static void main(String[] args) {
try {
Socket client = new Socket("localhost", 8);
System.out.println("Connected to server");
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter outToServer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
Scanner input = new Scanner(System.in);
String strClient,strServer;
while(true){
System.out.print("Client: ");
strClient = input.nextLine();
outToServer.write(strClient);
strServer = inFromServer.readLine();
System.out.print("Server: ");
System.out.println(strServer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
There are several problems with your code:
Your server is expecting to read a line and you're only writing text without a newline symbol:
Reading a line in server with: inFromClient.readLine()
Writing text without newline in client: outToServer.write(strClient);
Change this to outToServer.write(strClient + "\n");
You don't flush the writer of the client. Add a outToServer.flush(); after the line outToServer.write(...);
You only read 1 line in the server and don't read inside the loop again.
EDIT: To make it easier i'll post the corrected code here: (I've tried it and it works like a charm)
Client:
public class Client {
public static void main(String[] args) {
try (Socket client = new Socket("localhost", 8);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter outToServer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
Scanner input = new Scanner(System.in)) {
System.out.println("Connected to server");
String strClient,strServer;
while(true){
System.out.print("Client: ");
strClient = input.nextLine();
outToServer.write(strClient);
outToServer.newLine();
outToServer.flush();
strServer = inFromServer.readLine();
System.out.println("Server: " + strServer);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server:
public class Server {
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(8);
Socket client = server.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter outToClient = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()))) {
String in = inFromClient.readLine(), out;
while(in != null){
out = in + " from server";
outToClient.write(out);
outToClient.newLine();
outToClient.flush();
in = inFromClient.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Please remark that this solution uses Javas ARM (Automatic resource management) for autoclosing streams and sockets. So this will not work before java 1.7!
I have a socket client sending text to a socket server but the ReadLine doesnt seem to wait to receive a line before proceeding. Here is the of the server receiving the text:
public void run() {
try {
serveurSocket = new ServerSocket(PORT_ID);
connexionSocket = serveurSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(connexionSocket.getInputStream()));
PrintWriter writer = new PrintWriter(connexionSocket.getOutputStream(), true);
messageRecu = "";
while (true) {
messageRecu = reader.readLine();
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//reader.close();
//writer.close();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
After establishing the socket between client and server, the execution halts at reader.readLine until I send manually a string thru the socket. Which is normal and wanted. Codes resumes and its fine until its loops back to reader.ReadLine() where it will read a "null" line instead of waiting for input from the socket like it did the first time... this will obviously mess up the next command to uppercase. So how can I fix this?
EDIT: I'll add the client side if that can help understand.
public class ClientSocket {
private Socket clientSocket;
public boolean isClosed() { return clientSocket.isClosed(); }
public boolean connectToSocket (String ip, int port) {
try {
clientSocket = new Socket(ip, port);
return true;
}
catch (IOException e) {
System.out.println(e);
return false;
}
}
public String sendToServer(String messageClient) {
String messageRecu = "";
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);
writer.println(messageClient);
messageRecu = reader.readLine();
reader.close();
writer.close();
return messageRecu;
}
catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return messageRecu;
}
}
}
A button press will call "connectTosocket" to initiate the socket. A second button when pressed will send the content of a textfield using "sendToServer".
Server does receive the message and return it capitalized but I wish for the socket to remain open with the server and if I send an other string for the same sequence to happen. Not even sure it can be done :(
According to the documentation of BufferedReader#readLine, a null is returned if the end of stream has been reached.
Change your reading loop to :
while ((messageRecu = reader.readLine()) != null) {
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//Get out of the loop when the end of stream is reached.
As per Reading from and Writing to a Socket chapter of the Java tutorial.
As a side note, while(true) loops are not really appreciated.
The "null" signals for end of connection from the client side - which is why the connection disconnects. If you want to support multiple requests, you should run a new ServerSocket.accept() each time and wait for a new client to connect.
KKMultiServer class:
import java.net.*;
import java.io.*;
public class KKMultiServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java KKMultiServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
new KKMultiServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
KKMultiServerThread class:
import java.net.*;
import java.io.*;
public class KKMultiServerThread extends Thread {
private Socket socket = null;
public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can read more about sockets in Oracle tutorials
I am using Socket and ServerSocket classes to communicate on local host
client sends a no. to server and server computes square of no. and sends back to the client
// Client Class
import java.net.*;
import java.io.*;
class SocketDemo
{
public static void main(String...arga) throws Exception
{
Socket s = null;
PrintWriter pw = null;
BufferedReader br = null;
System.out.println("Enter a number one digit");
int i=(System.in.read()-48); // will read only one character
System.out.println("Input number is "+i);
try
{
s = new Socket("127.0.0.1",10101);
pw = new PrintWriter(s.getOutputStream());
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("Connection established, streams created");
}
catch(Exception e)
{
System.out.println("Exception in Client "+e);
}
pw.println(i);
System.out.println("Data sent to server");
String str = br.readLine();
System.out.println("The square of "+i+" is "+str);
}
}
// Server Side
import java.io.*;
import java.net.*;
class ServerSocketDemo
{
public static void main(String...args)
{
ServerSocket ss=null;
PrintWriter pw = null;
BufferedReader br = null;
int i=0;
try
{
ss = new ServerSocket(10101);
}
catch(Exception e)
{
System.out.println("Exception in Server while creating connection"+e);
}
System.out.print("Server is ready");
while (true)
{
System.out.println (" Waiting for connection....");
Socket s=null;
try
{
s = ss.accept();
System.out.println("Connection established with client");
pw = new PrintWriter(s.getOutputStream());
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
i = new Integer(br.readLine());
System.out.println("i is "+i);
}
catch(Exception e)
{
System.out.println("Exception in Server "+e);
}
System.out.println("Connection established with "+s);
i*=i;
pw.println(i);
try
{
pw.close();
br.close();
}
catch(Exception e)
{
System.out.println("Exception while closing streams");
}
}
}
}
Please Help
On client side do this after sending data to server
pw.println(i);
pw.flush();