server
public class Server {
class ServerHelper implements Runnable
{
InputStream is;
private InputStreamReader isr;
private BufferedReader br;
public ServerHelper(InputStream is) {
this.is = is;
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
}
private void display() throws IOException {
String s = "";
System.out.print("client says : ");
while ( ( s = br.readLine() ) != null ) {
System.out.print(s + " ");
}
}
#Override
public void run() {
try {
display( );
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
void start( ) throws Exception{
ServerSocket ss = new ServerSocket(5555);
while (true) {
System.out.println("waiting for conn..");
Socket accept = ss.accept();//code hangs over here and doesn't proceed ahead
if( accept == null )
System.out.println("got null...");
System.out.println("got the client req...");
ServerHelper sh = new ServerHelper(accept.getInputStream());
Thread t = new Thread(sh);
t.start();
}
}
public static void main(String[] args) {
try {
// TODO code application logic here
new Server().start();
} catch (Exception ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
client
public class Client {
void start( ) throws Exception{
System.out.println("enter window size ");
Scanner sc = new Scanner(System.in);
int wsize = sc.nextInt();
Socket s = new Socket("127.0.0.1", 5555);
System.out.println("is connected .." + s.isConnected());
OutputStream outputStream = s.getOutputStream();
PrintWriter pw = new PrintWriter(outputStream);
String c = "y";
int j = 0;
do{
String se = "";
for (int i = 0; i < wsize; i++) {
j++;
se = se + String.valueOf(j);
}
pw.println(se);
pw.flush();
System.out.println("do u wanna send more....?(y|n)");
c = sc.next();
}while( c.equalsIgnoreCase("y") );
}
public static void main(String[] args) {
try {
// TODO code application logic here
new Client().start();
} catch (Exception ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Socket accept = ss.accept();
here my code hangs up i know it is blocking io, but at the client side i did verify that whether client is connected or not but it is showing connected...whats the matter with accept() ? I code in similar manner for all my TCP applications but this is weird ..can any one help
I have also added the ServerHelper code for those who want take a look at that class please..
If the call to accept is really blocking, then you have another program running that is listening on 5555 and is bound to "127.0.0.1". Your client is connecting to this other program, so ss.accept still blocks.
The solution is to find and kill this other process
Additional information:
Since you did not specify the bind address in your server socket, it is bound to "0.0.0.0" (all interfaces).
It is possible to have one process bind to 127.0.01 and another to bind to 0.0.0.0 (at least on Windows). I copied some data from tcpview. The second column is process id.
java.exe 5944 TCP 0.0.0.0 5555 0.0.0.0 0 LISTENING
java.exe 5944 TCPV6 [0:0:0:0:0:0:0:0] 5555 [0:0:0:0:0:0:0:0] 0 LISTENING
java.exe 5608 TCP 127.0.0.1 5555 0.0.0.0 0 LISTENING
I can connect to the process 5944 using telnet 10.101.16.28 5555 (my local IP address) or connect to process 5608 using telnet 127.0.0.1 5555
Take a look on your code:
while (true) {
System.out.println("waiting for conn..");
Socket accept = ss.accept();
.................
}
You call ss.accept() into infinite loop. Once your client is connected accept() returns the Socket instance. Then you pass this socket to server helper running in its own thread and return to ss.accept(), so your server is ready to accept other clients. Your code looks OK. Unfortunately you have not sent code of your ServerHelper and did not explain whether your client successfully sends data to server, however so far everything looks fine.
Of course it blocks. It is waiting for a connection. That's what it's supposed to do. BTW checking the result of accept() for null is pointless. It won't be null. Possibly this is your misconception: are you expecting it to return null if there is no incoming connection? It doesn't do that. See the Javadoc.
Related
We just started studying IO codes and there is a certain point I don't understand this problem :
Here's the server Code :
public final class SuccServer {
public static void main(String[] args) {
try (ServerSocket s0 = new ServerSocket(5108);
Socket s = s0.accept();
BufferedReader r =
new BufferedReader(
new InputStreamReader(s.getInputStream(),
US_ASCII));
BufferedWriter w =
new BufferedWriter(
new OutputStreamWriter(s.getOutputStream(),
US_ASCII))) {
int i = Integer.parseInt(r.readLine());
int i1 = i + 1;
w.write(String.valueOf(i1));
w.write('\n');
w.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
And here's the Client code :
public final class SuccClient {
public static void main(String[] args) {
try (Socket s = new Socket("localhost", 5108);
BufferedReader r =
new BufferedReader(
new InputStreamReader(s.getInputStream(),
US_ASCII));
BufferedWriter w =
new BufferedWriter(
new OutputStreamWriter(s.getOutputStream(),
US_ASCII))) {
int i = 2019;
w.write(String.valueOf(i));
w.write('\n');
w.flush();
int succ = Integer.parseInt(r.readLine());
System.out.printf("succ(%d) = %d%n", i, succ);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
First the connection is established so the accept() creats the socket, then I don't understand how the code will work(chronologically), why is the client's write instruction
w.write(String.valueOf(i));
that is executed first and not the server's
int i = Integer.parseInt(r.readLine());
, and why after writing 2019 does the client wait for the server's response ? he could simply continue the code by executing
int succ = Integer.parseInt(r.readLine());
without waiting for the server to respond him with 2020 ?
These questions could seem simple but they don't let me understand more difficult code.
Simply put it's because readLine() and accept() are blocking.
"In computing, a process is an instance of a computer program that is being executed. A process always exists in exactly one process state. A process that is blocked is one that is waiting for some event, such as a resource becoming available or the completion of an I/O operation"
Program would hang at readline() until newline or end of stream is reached, just like when accept() is called on the server it hangs until a client connects.
edit: Here is another explanation with focus on network sockets.
I am new to sockets in JAVA. Recently, I am trying to build a server-client program that clients can search a word from the dictionary in server side and the server will return the defintion of the word to the clients. The code in server side is as the following:
public class DictionaryServer {
private static int port;
private static String dicFile;
static Map<String, String> dictionary = new HashMap<String, String>();
int userCounter = 0;
public static void main(String[] args) {
//check if starting the server in valid format
if (args.length != 2) {
System.err.println("Invalid format to start DictionaryServer");
System.err.println("Usage: java DictionaryServer <port number> <the name of dictionary>");
System.exit(1);
}
port = Integer.parseInt(args[0]);
dicFile = args[1];
try{
System.out.println("IP: " + InetAddress.getLocalHost());
System.out.println("port: " + port);
}
catch(UnknownHostException e){
e.printStackTrace();
}
DictionaryServer s = new DictionaryServer();
s.server(port, dicFile);
}
public void server(int port, String dicFile) {
ServerSocketFactory serverSocket = ServerSocketFactory.getDefault();
try(ServerSocket server = serverSocket.createServerSocket(port)){
System.out.println("Server IP: " + server.getInetAddress());
System.out.println("Listening for client connections...");
while(true){
Socket client = server.accept();
System.out.println("Client \"" + client.getRemoteSocketAddress().toString()
+ "\""+ " is connecting.");
Thread t = new Thread(() -> service(client, dicFile));
t.start();
}
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
public void service(Socket client, String dicFile){
try(Socket clientSocket = client){
// Input and Output stream of the client
DataInputStream input = new DataInputStream(
clientSocket.getInputStream());
DataOutputStream output = new DataOutputStream(
clientSocket.getOutputStream());
//check request
int action = input.readInt(); //1:add, 2:remove, 3:query
String word = input.readUTF();
//choose action
Dic d = new Dic(dicFile);
switch(action){
case 1: //add
String definition = input.readUTF();
output.writeUTF(d.add(word, definition, dicFile));
break;
case 2: //remove
output.writeUTF(d.remove(word, dicFile));
break;
case 3: //query
output.writeUTF(d.query(word, dicFile));
break;
}
}
catch(IOException e){
String message=e.getMessage();
System.out.println(message);
System.out.println();
}
}
I am got stucked in an error when I try to restart the serverprogram: java.net.BindException: Address already in use (Bind failed)
For example, last time I execute the server program with the port 4000 and it worked, but if I want to execute the server program with the same port again, the exception will show up. I checked what the port 4000 is doing by "lsof -i:4000" in terminal which told me:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 19683 Andy 7u IPv6 0x43e8f876eb74b731 0t0 TCP *:terabase (LISTEN)
Does anyone know how I can fix this problem? Thank you!
You need make sure your program has really exited, and you also need to set reuseAddress. To do that you have to create the server socket without binding, set the option, and then bind it, in three different steps:
ServerSocket server = serverSocketFactory.createServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(port));
UPDATE:
I noticed that it works fine on a Windows machine, but it fails on Mac.
I created a basic Java Server code for socket connection. It runs on AWS Linux AMI, and I make a client connection from my computer. It works fine for first 4-5 answers from the client. However, after 4th or 5th answer, I don't get any response from the server and it just hangs. After a while, it gives SocketTimeout Exception.
I set socket timeout with setSoTimeout() in both side, and it didn't change anything. I wonder if it has anything to do with Amazon.
Client Code:
public static void main(String[] args) {
final int portNumber = 9090;
String connected = "1";
System.out.println(WELCOME);
try {
Socket socket = new Socket("ip", portNumber);
socket.setSoTimeout(0);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out.println(connected);
while (connected.equals("1")) {
//read in situation
String situation = readInSituation(socket, input).replace(DELIMETER, "\n");
System.out.println(situation);
//send option
Scanner in = new Scanner(System.in);
System.out.print("Enter option: ");
out.println(in.nextLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readInSituation(Socket socket, BufferedReader input) throws Exception {
while (!input.ready()) {
Thread.sleep(200);
}
return input.readLine();
}
Server Code is more complicated, but all it does is to respond to commands and print basic text on the screen.
Thanks
Don't use PrintWriter over the network, as it swallows exceptions, most probably a prior 'connection reset'. Use BufferedWriter. NB The ready() loop is literally a waste of time.
I am trying to create a server that receives UDP packets and responds with UDP messages. However, I can't seem to get it to bind to a port. Here's my constructor for the class:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
DatagramChannel channel = DatagramChannel.open();
mySocket = channel.socket();
//mySocket = new DatagramSocket(null);
//mySocket.setReuseAddress(true);
//mySocket.bind(new InetSocketAddress("localhost", Constants.SERVER_PORT_NUM));
myPortNum = mySocket.getPort();
myIP = mySocket.getInetAddress();
System.out.println(myPortNum + " " + myIP.toString());
}
I have tried both the channel method and the commented out method, and I even used this method to try and find an open port:
private DatagramSocket createNewSocket() throws IOException {
for (int i = Constants.MIN_PORT_NUM; i < Constants.MAX_PORT_NUM; i++){
try {
System.out.println(i);
return new DatagramSocket(i);
} catch (IOException e){
continue; // try next port
}
}
throw new IOException("No free port found");
}
But I've had no luck so far. The portNum keeps coming up as -1 and the IP is null. Any ideas what could be going on here?
EDIT: When I run the following in debug mode and scroll over mySocket to see what values it contains, it says that:
bound = true
closed = false
connectedAddress = null
connectedPort = -1
But when I run mySocket.getLocalPort(), it returns a valid port number. What's going on here?
Here's the code:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
mySocket = new DatagramSocket(Constants.SERVER_PORT_NUM);
mySocket.setReuseAddress(true);
myPortNum = mySocket.getLocalPort();
myIP = mySocket.getInetAddress();
System.out.println(mySocket);
}
You don't need to do this. Just create it with the non-args constructor, or specify port zero. The system will allocate a free port for you.
I'm making a simple chat server and just made it so each connection runs on a new thread.
The old version started a single thread for the server, it did a while loop, which would stop when a stop message was sent then close the socket.
The new version loops forever and create a new thread for each new connection. Now I cannot close the socket connection.
If you press a key and the main thread stops, the socket stays open. Thus when I run the program again I need to change the socket number.
code of server
while(true)
{
///////////////////////////////////////////////////
// get a new connection
///////////////////////////////////////////////////
System.out.println("Aceepting connections on port 1030 \r");
try{
// Get New Connection
// wait for ever on accepting new connections
server.setSoTimeout(0);
connection=server.accept();
cConnection thread = new cConnection("thread3", connection);
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
}
code that starts server
Now each message comes in on a new thread, so I cannot tell it to stop and close the socket.
You need to provide a flag that must be globally accesible, so when some client wants to stop the server then change the variable ans stops the bucle. By example:
class YourServer {
private static boolean execute = true;
public static synchronized void stop() {
execute = false;
}
public void yourMethod() {
while(execute) {
// implement your server here
}
}
}
When a client send the command STOP you must be do
YourServer.stop();
If you want a stop command to stop the server you can call System.exit() to force the program to store or just closing server is likely to be all you need.
Looking into your problem, I understood one thing, that since you are putting
while (true), so your control always gets stuck at connection=server.accept(); listening for a new connection. So in order to stop the sockets you need to first find a way to stop looping in that while loop. Either you can set a Variable, like (int clientsConnected) to check the number of Clients, when that comes to zero stop that while loop. So you can stop your sockets.
Below is my sample code for clients which is doing the same thing for closing the Sockets.
Hopefully this solves your problem.
class GetNamesFromServer implements Runnable
{
private Socket sForName, sForId;
private BufferedReader in, inForName, inForId;
private PrintWriter outForName, outForId;
private static String clientNames;
public GetNamesFromServer(Socket s1, Socket s2)
{
sForName = s1;
sForId = s2;
}
public void run()
{
try
{
outForName = new PrintWriter(sForName.getOutputStream(), true);
outForName.println(Client.clientName);
System.out.println("Send Name : " + Client.clientName);
outForName.flush();
}
catch(IOException e)
{
System.err.println("Error sending Name to the Server.");
}
try
{
inForId = new BufferedReader(new InputStreamReader(sForId.getInputStream()));
Client.clientId = (inForId.readLine()).trim();
System.out.println("Client ID is : " + Client.clientId);
}
catch(IOException e)
{
System.err.println("Error Receiving ID from Server.");
}
try
{
inForName = new BufferedReader(new InputStreamReader(sForName.getInputStream()));
while (true)
{
clientNames = inForName.readLine();
if (clientNames != null && clientNames != "")
{
clientNames = clientNames.substring(1, clientNames.length() - 1);
System.out.println("Names Received : " + clientNames);
String[] names = clientNames.split(", ");
Client.nameClients.clear();
for (String element: names)
Client.nameClients.add(element);
Client.nPane.setText("");
int size = Client.nameClients.size();
System.out.println("Size of list : " + size);
for (int i = 0; i < size; i++)
{
String name = Client.nameClients.get(i);
String colour = Character.toString(name.charAt(0));
name = name.substring(1, name.length()) + "\n";
appendToNamePane(name, ReceiveMessages.getColour(Integer.parseInt(colour)), "Lucida Console");
}
System.out.println("Clients Online : " + Client.nameClients);
}
int index = Client.nameClients.indexOf(Client.clientId + Client.clientName);
**if (index == -1)
{
sForName.close();
break;
}**
}
}
catch(IOException e)
{
System.err.println("Error Receiving Names of Clients from Server");
}
}
NEW EDITION :
You can add a cap to maximum number of clients that can connect, once that reaches your while loop will not go to connection = server.accept(); and hence when they are done chatting (after some time) i.e. totalClients = 0, you can stop your sockets as well, to stop the program.
if (totalClients == 0)
{
socket.close();
serverSocket.close();
}
Regards