Im trying to code a simple server that creates a chat between any two clients that connect to the server. (for any two new clients the server will open a new chat thred/s and then will wait to the next two clients)
i have tried the followןng solution:
Server:
public class Server
{
public Server() throws IOException
{
ServerSocket sc = new ServerSocket(7777);
Socket s1, s2;
while(true)
{
s1 = sc.accept();
s2 = sc.accept();
new ServerThread(s1, s2).start();
new ServerThread(s2, s1).start();
}
}
}
Server threads (two threads as explained in the comment above the class)
/*
Receives message from sender socket and pass them to the recipient socket
*/
public class ServerThread extends Thread
{
Socket sender;
Socket recipient;
public ServerThread(Socket sender, Socket recipient)
{
this.sender = sender;
this.recipient = recipient;
}
#Override
public void run()
{
try {
handle();
} catch (IOException e) {
e.printStackTrace();
}
}
public void handle() throws IOException
{
String msg;
// Create output stream for the recipient
OutputStream outputStream = recipient.getOutputStream();
ObjectOutputStream objOutputStream = new ObjectOutputStream(outputStream);
// Create input stream for the recipient
InputStream inputStream = sender.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
while(true) //sender.isConnected())
{
msg = objectInputStream.readUTF();
if(true) //recipient.isConnected())
objOutputStream.writeUTF(msg);
else
break;
}
sender.close();
recipient.close();
}
}
(Please note that i removed the condotion in the "while" and "if" since i wanted to eliminate anything that will might appear because of it)
Clients main:
public class ClientMain
{
public static void main(String[] args)
{
String s;
Scanner scan = new Scanner(System.in);
try {
ClientChat chat = new ClientChat("localhost", 7777);
//while true gets messages if any and print them to the console
chat.getMessages();
s = scan.nextLine();
while(!s.equals("1"))
{
chat.sendMessage(s);
s = scan.nextLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Clients Thread:
public class ClientChat
{
Socket socket;
String ip;
int port;
OutputStream outputStream;
ObjectOutputStream objOutputStream;
InputStream inputStream;
ObjectInputStream objectInputStream;
public ClientChat(String ip, int port) throws UnknownHostException, IOException
{
this.ip = ip;
this.port = port;
socket = new Socket(ip, port);
// Create output stream for the recipient
outputStream = socket.getOutputStream();
objOutputStream = new ObjectOutputStream(outputStream);
// Create input stream for the recipient
inputStream = socket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
}
public void getMessages() throws IOException
{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(true)//socket.isConnected())
{
String msg;
try {
msg = objectInputStream.readUTF();
System.out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
public void sendMessage(String message)
{
try {
objOutputStream.writeUTF(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Well, this code doesn't work,
I have run the server and two clients, the clients do connect to the server, and you can
enter input to readLine() method, but nothing happen.
i have tried to dubug the server, what i found is that it stack on the line:
msg = objectInputStream.readUTF();
that all the relevant info i have, if you need some more information please comment
You need to call the flush() method from the ObjectOutputStream object. If you don't the data to send are stored in an internal buffer. It will get only send when the buffer is full or when you explicit call the flush() method.
Related
I'm developing a client-server app, and my server can receive connection requests from 2 types of clients, therefore I instanciate the ObjectInputStream directly in my server, to recognize the client type (client or worker) and then I have a Thread for each type of client.
While initializing the thread, I pass as an argument the socket which I created in the server. (code below)
public class Server {
public int PORT;
private ArrayList<DealWithClient> connectedClients;
private ArrayList<DealWithWorker> connectedWorkers;
private ArrayList<String> types = new ArrayList<>();
private BlockingQueue<Runnable> tasks = new BlockingQueue<>();
private SearchTypes searchTypes;
private ObjectOutputStream out;
private ObjectInputStream in;
public static void main(String[] args) {
new Server(args[0]);
}
public Server(String port) {
this.PORT = Integer.parseInt(port);
startServing();
}
public void startServing() {
connectedClients = new ArrayList<>();
connectedWorkers = new ArrayList<>();
try {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Lançou ServerSocket: " + s);
try {
while (true) {
Socket socket = s.accept();
inscription(socket);
}
} finally {
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void inscription(Socket socket) {
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
Object obj = in.readObject();
if(obj instanceof String) {
String inscriptionMessage = (String) obj;
System.out.println("Mensagem recebida: " + obj);
if(inscriptionMessage.contains("Inscrição cliente")) {
DealWithClient dwc = new DealWithClient(socket, this);
dwc.start();
addClient(dwc);
out.writeObject(searchTypes);
}
if(inscriptionMessage.contains("Inscrição worker")) {
String[] worker = inscriptionMessage.split(" ");
searchTypes = new SearchTypes(worker[4]);
DealWithWorker dww = new DealWithWorker(socket, this);
dww.start();
addWorker(dww);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
public void addClient(DealWithClient client) {
connectedClients.add(client);
System.out.println("Cliente adicionado! »» " + client.toString());
}
public void addWorker(DealWithWorker worker) {
connectedWorkers.add(worker);
System.out.println("Worker adicionado! »» " + worker.toString());
}
My DealWithClient code below, is where I'm having the problem, since that I can not reach the System.out.println("BBB"), because it gets stuck in the instanciation of ObjectInputStream.
public class DealWithClient extends Thread{
private Socket socket;
private Server server;
private ObjectInputStream in;
private ObjectOutputStream out;
private Client client;
public DealWithClient(Socket socket, Server server) {
this.server = server;
this.socket = socket;
}
#Override
public void run() {
try {
connectToServer();
} catch (IOException e) {
e.printStackTrace();
}
while(!interrupted()) {
treatClientRequests();
}
}
private void connectToServer() throws IOException {
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("AAA");
in = new ObjectInputStream(socket.getInputStream());
System.out.println("BBB");
}
I've looked for similar questions around here, but I didn't managed to find one that could solve my issue.
My question is, once I instanciate the ObjectInput and ObjectOutput streams in the server, I cannot do it again inside my Thread?
Thanks!
You are most likely getting a deadlock error because the socket is still being used by ObjectOutputStream when you are trying to get an Input stream from the same socket. Try calling the close() method on out before instantiating the ObjectInputStream below. Calling the close() method will free up resources.
This is code provided to me for a class. I am trying trying to fix a connection problem between the client and server. Even when both are started they do not connect.
This is for a Java based game of Battleship that will allow two users on separate devices to play one another. I'm not sure why the two do not connect and even the debugger has not been much help in directing me to the problem.
public class GameClient
{
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void openConnection(String ip, int port)
{
try
{
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
catch (Exception e)
{
System.out.println("Error opening client socket");
}
}
public String sendMessage(String msg)
{
String resp = "";
try
{
out.println(msg);
resp = in.readLine();
}
catch (Exception e)
{
System.out.println("Error sending message from Client");
}
return resp;
}
public void stop()
{
try
{
in.close();
out.close();
clientSocket.close();
}
catch (Exception e)
{
System.out.println("Error stopping client");
}
}
public static void main(String[] args)
{
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
String response = client.sendMessage("1,2");
System.out.println(response);
client.stop();
}
}
public class GameServer
{
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port)
{
try
{
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String move = in.readLine();
System.out.println(move);
out.println("6,1");
}
catch (Exception e)
{
System.out.println("Socket opening error");
}
}
public void stop()
{
try
{
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
catch (Exception e)
{
System.out.println("Error closing sockets");
}
}
public static void main(String [] args)
{
GameServer server = new GameServer();
server.start(3333);
server.stop();
}
}
public class PlayBattleship
{
public static void main(String[] args)
{
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
//System.out.println(response);
BattleshipGame game = new BattleshipGame();
while (!game.checkEndgame())
{
game.getGuess(client);
}
client.stop();
}
}
The client and server should connect and stay connected till the game has reached completion
EDIT: I have thoroughly read the API documentation but still cannot understand the problem.
The Server in your code isn't waiting for the incoming requests, it only serves a single incoming request and then kills itself due to the nature of the main method which starts it.
You need to have the server wait for the requests and do not die. Check the code snippet below to understand the logic.
Plus, always try to throw the exceptions if you can't do anything meaningful with it within the method it is caught in. In your code the main method of the server will anyway execute even if there is an exception caught in the start method
public class GameServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public ServerSocket start(int port) throws IOException {
serverSocket = new ServerSocket(port);
return serverSocket;
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
// This method accepts and serves the incoming requests
public void acceptConnection(ServerSocket serverSocket) throws IOException {
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String move = in.readLine();
System.out.println(move);
out.println("6,1");
}
public static void main(String[] args) throws IOException {
GameServer server = new GameServer();
ServerSocket serverSocket = server.start(3333);
System.out.println("Server Started");
// The effective change you need to make
// Loop through the incoming requests
while(true) {
server.acceptConnection(serverSocket);
}
}
}
public class GameClient {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void openConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public String sendMessage(String msg) throws IOException {
String resp = "";
out.println(msg);
resp = in.readLine();
return resp;
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
}
public static void main(String[] args) throws IOException {
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
String response = client.sendMessage("1,2");
System.out.println(response);
client.stop();
}
}
This question already has an answer here:
ObjectInputStream(socket.getInputStream()); does not work
(1 answer)
Closed 7 years ago.
I'm doing a simple echo chat and server, but methods send and receive in class Connection don't work with ObjectInputStream and ObjectOutputStream, but with PrintWriter and BufferedReader work fine.
Now I'm trying to understand the serialization using sockets, help me to understand why this code does not work:
Client
public class Client {
private Connection connection;
private String getServerAddress() {
return "localhost";
}
private int getServerPort() {
return 4444;
}
public void run() {
BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
try {
connection = new Connection(new Socket(getServerAddress(), getServerPort()));
SocketThread socketThread = new SocketThread();
socketThread.setDaemon(true);
socketThread.start();
while (true) {
String text = bis.readLine();
if (text.equalsIgnoreCase("exit"))
break;
connection.send(text);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.run();
}
public class SocketThread extends Thread {
#Override
public void run() {
try {
while (true) {
String message = connection.receive();
System.out.println(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Connection
public class Connection implements Closeable {
private final Socket socket;
private final ObjectInputStream in;
private final ObjectOutputStream out;
public Connection(Socket socket) throws Exception {
this.socket = socket;
this.in = new ObjectInputStream(socket.getInputStream());
this.out = new ObjectOutputStream(socket.getOutputStream());
}
public void send(String message) throws Exception {
out.writeObject(message);
}
public String receive() throws Exception {
return (String) in.readObject();
}
#Override
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
}
Server
public class Server {
public static void main(String[] args) {
int port = 4444;
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true) {
Socket socket = serverSocket.accept();
new Handler(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static class Handler extends Thread {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try (Connection connection = new Connection(socket)) {
while (true) {
String message = connection.receive();
if (message.equals("exit"))
break;
System.out.println(message);
connection.send("Echo: " + message);
}
} catch (Exception e) {
}
}
}
}
This is because ObjectInputStream blocks trying to read the stream header written by an ObjectOutputStream in its constructor, and you are creating both of your input streams before the output streams. You can solve this by switching the order that you create the object streams in:
this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(socket.getInputStream());
The javadoc for the ObjectOutputStream constructor also notes that you might want to flush the stream after creating it to ensure the header is sent.
So I have a client:
public class TalkClient extends Thread
{
private int port;
private String host;
DocCntl theDocCntl;
public TalkClient(String host, int port) throws IOException
{
this.host = host;
this.port = port;
theDocCntl = new DocCntl(this);
}
public void run()
{
try
{
System.out.println("Seeking connection...");
Socket socket = new Socket(host, port);
DataInputStream in = new DataInputStream(socket.getInputStream());
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
}catch(IOException e)
{
e.printStackTrace();
}
}
public static void main(String [] args)
{
int port = 5050;
try
{
Thread t = new TalkClient("127.0.0.1", port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
public void pushToServer(){
String theData = this.theDocCntl.theDoc.docTA.getText();
}
}
And I have a server:
public class TalkServer extends Thread
{
private ServerSocket serverSocket;
public static DocCntl theCntl;
public TalkServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
}
public void run()
{
try
{
System.out.println("Listening for connections...");
Socket client = serverSocket.accept();
DataInputStream in = new DataInputStream(client.getInputStream());
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream out = new DataOutputStream(client.getOutputStream());
}catch(IOException e)
{
e.printStackTrace();
}
}
public static void main(String [] args)
{
int port = 5050;
try
{
Thread t = new TalkServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
In the client, I have a method called pushToServer, which I want to take the String data from a textArea on the client, and then push that to all the other connected clients. But I'm not sure how to handle sending the message to each individual connected client through the sockets. I've given it some thought, and I think I need to do 3 things:
1) Create and maintain a list of connected clients(threads). In the server class itself? Or in another class?
2) On the server, have some means of 'catching' the String data from one client, and then pushing it to all the other clients. This is why(I think) I need the list of clients. If I can figure out how to catch this(maybe through the input stream?) and then iterate through the list of clients to their text areas.
3) On the client side, I need to be able to catch the string from the server.
Any help on these 3 things would be greatly appreciated.
I'm trying to write a little SocketServer and a fitting ClientApplet. The connection works (I echo out incoming/closing connections), but the server does not get any InputStream.
I just can't fix the problem and feel a bit lost :/
The complete project is here.
Here is the responsible part of my server:
MessageService.java
public class MessageService implements Runnable {
private final Socket client;
private final ServerSocket serverSocket;
MessageService(ServerSocket serverSocket, Socket client) {
this.client = client;
this.serverSocket = serverSocket;
}
#Override
public void run() {
PrintWriter out = null;
BufferedReader in = null;
String clientName = client.getInetAddress().toString();
try {
out = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line;
System.out.println("Waiting for "+clientName);
/* HERE I TRY TO GET THE STREAM */
while((line = in.readLine()) != null) {
System.out.println(clientName + ": " + line);
out.println(line);
out.flush();
}
}
catch (IOException e) {
System.out.println("Server/MessageService: IOException");
}
finally {
if(!client.isClosed()) {
System.out.println("Server: Client disconnected");
try {
client.close();
}
catch (IOException e) {}
}
}
}
}
Part of Client
QueueOut.java
public class QueueOut extends Thread {
Socket socket;
public ConcurrentLinkedQueue<String> queue;
PrintWriter out;
public QueueOut(Socket socket) {
super();
this.socket = socket;
this.queue = new ConcurrentLinkedQueue<String>();
System.out.print("OutputQueue started");
}
#Override
public void start() {
try {
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("Running outputqueue");
while(true) {
if(this.queue.size() > 0) {
String message = this.queue.poll();
System.out.println("Sending "+message);
out.println(message+"\n");
}
}
}
catch (IOException ex) {
System.out.println("Outputqueue: IOException");
}
}
public synchronized void add(String msg) {
this.queue.add(msg);
}
}
I have reduced my post to the (as i think) necessary parts :)
Try getting your input stream before you get the output stream, even though you're not using it, you should match the inverse order on your client and your server (as discussed in another similar threads).
Edit:
Also see Socket programming
Good Luck!