The problem i have is that when i open a second client, the server doesn't seem to detect that a second client was opened. With the first time the client being opened it works fine and the server detects that a client has been connected.
Server:
public class Server {
Socket previousSocket = null;
private static int port = 9001;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("[SERVER] Server successfully launched on port: " + port);
DatagramSocket UDPSocket = new DatagramSocket(9002);
Socket previousSocket = null;
while (true) {
Socket newSocket = serverSocket.accept();
System.out.println("new client connected");
if (previousSocket == null) {
previousSocket = newSocket;
System.out.println("1 st client");
} else {
System.out.println("2 nd client");
previousSocket = null;
}
byte[] data = new byte[500];
DatagramPacket received = new DatagramPacket(data, data.length);
while(true) {
UDPSocket.receive(received);
String receivedData = new String(received.getData());
System.out.println(receivedData);
}
}
}
}
Client:
public ChatClient() throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 9001);
Scanner scanner = new Scanner(System.in);
DatagramSocket UDPSocket = new DatagramSocket();
while(scanner.hasNextLine()) {
String message = scanner.nextLine();
InetAddress ip = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, ip, 9002);
UDPSocket.send(packet);
}
}
The following loop will never end, that's the reason for your problem
while(true) {
UDPSocket.receive(received);
String receivedData = new String(received.getData());
System.out.println(receivedData);
}
I'm an amateur in java socket programming. As I say in title, When I using PrintStream for socket output,it works;but it doesn't work if I using simply OutputStream.
I know the the client connected to the server cause' the server got the info of the client.So I think there must be something wrong with I/O stream, not the socket connection.
btw, I even use the flush() method for OutputStream.I think flush() will force to send all bytes, but it seems like it didn't work.
The Client Code:#line 12:
public class Clinet {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("==========Client============");
Socket socket = new Socket("localhost", 8888);// Server's addr and port
socket.setSoTimeout(3000);
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
String msgToSent = "Hello TCP";
outputStream.write(msgToSent.getBytes());
outputStream.flush();// FIXME:why flush() didn't work?why msg wasn't sent.
// read from socket input
String receivedMsg = new String(inputStream.readAllBytes());
System.out.println(receivedMsg);
socket.close();
}
}
When I using a filter stream like PrintStream,the msg can be sent to server.
The Server Code: if using PrintStream it will work perfectly with the Client:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket client = serverSocket.accept();
new Thread(new ServerHandler(client)).start();
}
}
}
class ServerHandler implements Runnable {
private Socket client;
ServerHandler(Socket client) {
this.client = client;
}
#Override
public void run() {
try {
InetAddress clientAddr = client.getInetAddress();
int clientPort = client.getPort();
System.out.println("client connected # " + clientAddr + ":" + clientPort);
InputStream inputStream = client.getInputStream();
OutputStream outputStream = client.getOutputStream();
while (true) {
String msg = new String(inputStream.readAllBytes());// FIXME: Why Server didn't receive Client's msg?
System.out.print("/" + clientAddr + "#" + clientPort + " : ");
System.out.println(msg);
String reply = "I received " + msg.length() + " words.";// return how many words the server got.
outputStream.write(reply.getBytes());
outputStream.flush();// flush to ensure send all msg,but seems doesn't work
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am sorry, I have searched but seem that all the answers dont fix my problem. I got this error when trying to create a ServerSocket to reply to multiple client message.
My server code:
package Server;
import java.net.*;
import java.io.*;
public class Server {
public final static int defaultPort = 7;
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(defaultPort);
int i = 0;
while (true) {
try {
System.out.println("Server is running on port "
+ defaultPort);
Socket s = ss.accept();
System.out.println("Client " + i + " connected");
RequestProcessing rp = new RequestProcessing(s, i);
i++;
rp.start();
} catch (IOException e) {
System.out.println("Connection Error: " + e);
}
}
} catch (IOException e) {
System.err.println("Create Socket Error: " + e);
} finally {
}
}
}
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
DatagramSocket ds = new DatagramSocket(7);
while (true) {
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
String theString = new String(incoming.getData(), 0,
incoming.getLength());
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
ds.close();
break;
}
theString = theString.toUpperCase();
DatagramPacket outsending = new DatagramPacket(
theString.getBytes(), incoming.getLength(),
incoming.getAddress(), incoming.getPort());
System.out.println("Server reply to Client "
+ clientNo + ": " + theString);
ds.send(outsending);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
and my Client code:
package Client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
public class Client extends Object {
public final static int serverPort = 7;
public static void main(String[] args) {
try {
DatagramSocket ds = new DatagramSocket();
InetAddress server = InetAddress.getByName("192.168.109.128");
Socket s = new Socket("192.168.109.128", 7);
String theString = "";
do {
System.out.print("Enter message: ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
theString = br.readLine();
byte[] data = theString.getBytes();
DatagramPacket dp = new DatagramPacket(data, data.length,
server, serverPort);
ds.send(dp);
System.out.println("Sent to server server: " + theString);
byte[] buffer = new byte[6000];
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
System.out.print("Server reply: ");
System.out.println(new String(incoming.getData(), 0, incoming
.getLength()));
} while (!"quit".equals(theString));
s.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
With the first Client connect, it works smoothly. But from the second Client, it throws java.net.BindException: Address already in use: Cannot bind.
Second Client can also send and receive message, but the Client No is still 0.
Server is running on port 7
Client 0 connected
Server is running on port 7
Client 0 sent: msg 0
Server reply to Client 0: MSG 0
Client 1 connected
Server is running on port 7
java.net.BindException: Address already in use: Cannot bind
Client 0 sent: msg 1 <<-- this one is sent from client 1 but Client No is 0
Server reply to Client 0: MSG 1
So, in RequestProcessing.run you decide to ignore the socket received at constructor and open a DatagramSocket on the same port as the one you are listening. What did you expect it will happen?
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
// *****************
// The processor should be using this socket to communicate
// with a connected client *using TCP Streams*
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
// *****************************
// But, instead of using the this.channel, your code
// decides to ignore the TCP socket,
// then open another UDP *"server-side like"* socket.
// First time it's OK, but the second thread attempting
// to open another DatagramSocket on the same port will fail.
// It's like attempting to open two TCP ServerSockets on the
// same port
DatagramSocket ds = new DatagramSocket(7);
[Extra]
You will need to decide what protocol you'll be using: if you use a ServerSocket/Socket pair, then probably you want TCP communications, so no DatagramSockets.
If you want UDP communication, the ServerSocket/Socket has little to do with your approach and you'll need to use DatagramSocket. Construct it:
with a port on the serverside - and do it only once.
without any port for the client side then qualify each and every DatagramPackets with the server address and port.
See a tutorial on Oracle site on Datagram client/server configurations.
Everytime you receive a new client TCP connection on your main server socket, you spin up another instance of a RequestProcessing class. The first time you start the RequestProcessing instance thread, it successfully binds to UDP port 7. But then the second client connects and you try to spin up another instance of RequestProcessing while another one already exists. That's not going to work.
You should probably amend you protocol such that the RequestProcessing class picks a new port each time and signals back through to the TCP socket which port was chosen.
But if it was me, I would do this. Have a single RequestProcessing instance for all clients. Given that your UDP echo socket is just sending back a response to the address from which the packet arrived from, you only need one instance of this class.
A TCP solution:
An utility class (I'm too lazy to write the same code in multiple places):
public class SocketRW {
Socket socket;
BufferedReader in;
PrintWriter out;
public SocketRW(Socket socket)
throws IOException
{
super();
this.socket = socket;
if(null!=socket) {
this.in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out=new PrintWriter(socket.getOutputStream());
}
}
public String readLine()
throws IOException {
return this.in.readLine();
}
public void println(String str) {
this.out.println(str);
}
public Socket getSocket() {
return socket;
}
public BufferedReader getIn() {
return in;
}
public PrintWriter getOut() {
return out;
}
}
Server code - no more datagrams, just using Input/Output streams from the sockets, wrapped as Reader/Writer using the utility
public class TCPServer
implements Runnable // in case you want to run the server on a separate thread
{
ServerSocket listenOnThis;
public TCPServer(int port)
throws IOException {
this.listenOnThis=new ServerSocket(port);
}
#Override
public void run() {
int client=0;
while(true) {
try {
Socket clientConn=this.listenOnThis.accept();
RequestProcessing processor=new RequestProcessing(clientConn, client++);
processor.start();
} catch (IOException e) {
break;
}
}
}
static public void main(String args[]) {
// port to be provided as the first CLI option
TCPServer server=new TCPServer(Integer.valueOf(args[0]));
server.run(); // or spawn it on another thread
}
}
class RequestProcessing extends Thread {
Socket channel;
int clientNo;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
SocketRW utility=new SocketRW(this.channel);
while (true) {
String theString=utility.readLine().trim();
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
this.channel.close();
break;
}
theString = theString.toUpperCase();
utility.println(theString);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
Client code - no more datagram sockets, using the same IO streams of the socket.
class TCPClient
implements Runnable // just in case you want to run multithreaded clients
{
Socket socket;
public TCPClient(InetAddress serverAddr, int port)
throws IOException {
this.socket=new Socket(serverAddr, port);
}
public void run() {
String theString="";
InputStreamReader isr = new InputStreamReader(System.in);
try {
SocketRW utility=new SocketRW(this.socket);
BufferedReader br = new BufferedReader(isr);
do {
System.out.print("Enter message: ");
theString = br.readLine().trim();
utility.println(theString);
System.out.println("Sent to server server: " + theString);
String received=utility.readLine();
System.out.println("Server reply: "+received);
} while (!"quit".equals(theString));
}
catch(IOException e) {
e.printStackTrace();
}
}
static public void main(String[] args) {
int port=Integer.valueOf(args[0]); // will throw if its no OK.
TCPClient client=new TCPClient(
InetAddress.getByName("192.168.109.128"),
port
);
client.run();
}
}
i want to make communication between android device and java server.
Server side:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
PrintStream pw = new PrintStream(out);
pw.print("hello");
pw.flush();
socket.close();
Android client side :
public class connectTask extends Thread {
#Override
public void run() {
super.run();
while (true) {
try {
Socket socket = new Socket("192.168.0.101", 4444);
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = reader.readLine();
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(line);
}
});
socket.close();
} catch (IOException e) {
}}}}
and starting thread this way:
thread = new Thread(new connectTask());
thread.start();
the problem is I cannot get anything from java server. I either send or receive data wrong and i can't figure out what's the issue, what am I doing wrong here?
Your code looks good (may be String line = ... should be final String line = ...) and IP address and port of Server need to be checked.
I'm having the following TCP client code:
public static void register(InetAddress ip, int port, String name) {
try {
Socket clientSocket = new Socket(ip, port);
send("reg:" + name);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void send(String str) {
try {
String sentence = str;
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(sentence);
} catch (IOException e) {
Log.e("CONNECT", e.getMessage());
}
}
They both are called in onClicks and i know that for sure.
I also have the following Server code:
public static void main(String argv[]) throws Exception {
String clientSentence;
ServerSocket welcomeSocket = new ServerSocket(9876);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(
connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
outToClient.writeBytes("msg: Hello! kalin pedro");
}
}
When trying to send data to the server i don't get an exception, i also know that I'm connected to it because the application is crashing when i terminate the server application. The problem is that the server doesn't receive anything until i terminate the client application. Everything that i have tried to send until that moment is all received from the server at once. I looked at the network activity tab provided by Android Studio and there is a change when sending data, the server just doesn't receive it(or at least i don't see it receive it) until i terminate the client application.