Im developing a client-server app. The client side is Java based, the server side is C++ in Windows.
Im trying to communicate them with Sockets, but im having some trouble.
I have succesfully communicated the client with a Java Server, to test if it was my client that was wrong, but its not, it seems like im not doing it right in the C++ version.
The java server goes like this:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args){
boolean again = true;
String mens;
ServerSocket serverSocket = null;
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(12321);
System.out.println("Listening :12321");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(again){
try {
System.out.println("Waiting connection...");
socket = serverSocket.accept();
System.out.println("Connected");
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
while (again){
mens = dataInputStream.readUTF();
System.out.println("MSG: " + mens);
if (mens.compareTo("Finish")==0){
again = false;
}
}
} catch (IOException e) {
System.out.println("End of connection");
//e.printStackTrace();
}
finally{
if( socket!= null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
}
if( dataInputStream!= null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataOutputStream!= null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
System.out.println("End of program");
}
}
The client just makes a connection and sends some messages introduced by the user.
Could you please give me a similar working server but in C++ (in Windows)?
I can't make it work by myself.
Thanx.
Your problem is that you are sending a java string which could take 1 or 2 bytes per character (see bytes of a string in java?)
You will need to send and receive in ascii bytes to make things easier, imagine data is your data string on the client side:
byte[] dataBytes = data.getBytes(Charset.forName("ASCII"));
for (int lc=0;lc < dataBytes.length ; lc++)
{
os.writeByte(dataBytes[lc]);
}
byte responseByte = 0;
char response = 0;
responseByte = is.readByte();
response = (char)responseByte;
where is and os are the client side DataInputStream and DataOutputStream respectively.
You can also sniff your tcp traffic to see what's going on :)
Related
Im flabbergasted.
I took code from https://docs.oracle.com/javase/tutorial/networking/sockets/examples/EchoServer.java
for the server. And
https://docs.oracle.com/javase/tutorial/networking/sockets/examples/EchoClient.java
for the Client. I made minor changes. Mostly so that there is no back and forth echoing. Rather the Server should constantly with 2 second delays send same string. But I just cant understand why the client isnt working.
It sends the Exception message:
Couldn't get I/O for the connection to 127.0.0.1
I run the server with: java 6788
and the client with: 127.0.0.1 6788
I tried other ports.
I do this in eclipse so I set the arguments in Runconfiguration before running the classes. I start the server first. I tried in terminal outside of eclipse. Nothing makes it work.
Basically, the client should connect to server and output with System.out.println() what the server in turn outputs to the client. But nothing happens.
what is wrong?
Client:
import java.io.*;
import java.net.*;
public class EchoClient {
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.err.println(
"Usage: java EchoClient <host name> <port number>");
System.exit(1);
}
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
try (
Socket echoSocket = new Socket(hostName, portNumber);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
) {
String userInput;
while (true) {
System.out.println("recieved: " + in.readLine());
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
Server:
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java EchoServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
System.out.println(args[0]);
InetAddress add = InetAddress.getLocalHost();
System.out.println(add.getHostAddress());
try (
ServerSocket serverSocket =
new ServerSocket(Integer.parseInt(args[0]));
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream());
) {
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.println("HELLO!");
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
You have to send the answer to the client.
Add a out.flush();
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("HELLO!");
out.flush();
}
As in the comment I eventually found a solution. BufferedReader.readLine() "blocked". When reading from a file it returns a line after reading up to a newline character, if I understand it correctly.
But since it was "A steady flow" from server with no newlines, it just kept "reading" and never returned a String.
I then tried using BufferedReader.read() method, that reads character by character, and returns after each char (thus never blocking). It then prints each character as it arrives, also it listens for a newline being sent from server, and once a read character equals a newline, it then prints a newline instead. Sort of emulating the "read line" behaviour I was expecting from original question.
Reading part of client:
while(true) {
character = (char) reader.read();
if(Character.isISOControl(character)) {
System.out.println();
}
else {
System.out.printf("%c", character);
}
}
Sending Part of Server:
private String message = "HELLO\n";
...
while(true) {
try {
Thread.sleep(2000);
writer.write(message);
writer.flush();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm working on a program involving a multithreaded server, in which I want messages sent by clients to be echoed back to every client currently connected to the server. It doesn't exactly do this. I will send a message from a client to the server, and it will echo back to that same client. Not to the other client. Let's say, with one client I sequentially type "One" then "Two" then "Three". The exchange will be something like this:
Client 1: "One"
Echo from Server ON Client 1's console: "One"
Client 1: "Two"
Echo from Server ON Client 1's console: "Two"
Client 1: "Three"
Echo from Server ON Client 1's console: "Three"
This part does what it should. But absolutely nothing happens on Client 2's console. Let's say the exchange above has already happened. Client 2's screen will still be blank. I will then type something in Client 2, let's say "Test". The server will respond to Client 2 with "One". Let's say I type "Test" again in Client 2. The server will respond with "Two". You get the idea. I'm not sure why it's doing this. I have three files involved, The Client, The Server, and one meant to manage connections between them.
EDIT: I THINK I KNOW THE PROBLEM! On line 43 in client, the console expects some user input before it will proceed. Which I THINK is why when the first client sends user input, it gets a correct reply, but the second one doesn't: because the second client didn't enter anything in the console, and it's still waiting for some input in order to proceed. Any ideas on how to work around this?
Client:
package client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
//The socket for the client
Socket sock;
//The stream to read incoming data
DataInputStream din;
//The stream to send outgoing data
DataOutputStream dout;
public static void main(String[] args) {
//Create a new client
new Client();
}
public Client() {
try {
//Activate the socket to the host and port
sock = new Socket("localhost", 4444);
//Open the input and output streams
din = new DataInputStream(sock.getInputStream());
dout = new DataOutputStream(sock.getOutputStream());
//Start listening for user input
listenIn();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void listenIn() {
//Monitors the console for user input
Scanner userIn = new Scanner(System.in);
while(true) {
//While there is nothing left to read from the console
while(!userIn.hasNextLine()) {
try {
//Ensures resources aren't constantly being used by listening for input
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Get line from user input
String input = userIn.nextLine();
//if user exits the client, break the loop and exit the program
if(input.toLowerCase().equals("quit")) {
break;
}
try {
//outputs user input to Server
dout.writeUTF(input);
//Flushes all data out of the data output stream's buffer space
dout.flush();
//While there's nothing to read from the input stream, save resources
while(din.available() == 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//When there's incoming data, print it to the console
String reply = din.readUTF();
System.out.println(reply);
} catch (IOException e) {
e.printStackTrace();
break;
}
}
//Close all the I/O streams and sockets, so there aren't memory leaks
try {
din.close();
dout.close();
sock.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
//The server's socket
ServerSocket sSock;
ArrayList<ServerConnection> connections = new ArrayList<ServerConnection>();
boolean run = true;
public static void main(String[] args) {
//Create a new server
new Server();
}
public Server() {
try {
//Initialize the server socket to the correct port
sSock = new ServerSocket(4444);
//While the socket should be open
while(run) {
//Initialize the client socket to the correct port
Socket sock = sSock.accept();
//Create a new server connection object between the client socket and the server
ServerConnection sConn = new ServerConnection(sock, this);
//Start the thread
sConn.start();
//Add the connection to the arraylist
connections.add(sConn);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server Connection:
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class ServerConnection extends Thread{
Socket sock;
Server server;
DataInputStream in;
DataOutputStream out;
boolean run = true;
//Create the server connection and use super to run it with Thread's constructor
public ServerConnection(Socket socket, Server server) {
super("ServerConnectionThread");
this.sock = socket;
this.server = server;
}
public void sendOne(String text) {
try {
//Write the text to the output stream
out.writeUTF(text);
//Flush the remaining data out of the stream's buffer space
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
//Send a string to every client
public void sendAll(String text) {
/*Iterate through all of the server connections in the server
and send the text to every client*/
for(int i = 0; i < server.connections.size(); i++) {
ServerConnection sc = server.connections.get(i);
sc.sendOne(text);
}
}
public void run() {
try {
//Set the input stream to the input from the socket
in = new DataInputStream(sock.getInputStream());
//Set the output stream to write out to the socket
out = new DataOutputStream(sock.getOutputStream());
//While the loop should be running (as determined by a boolean value)
while(run) {
//While there is no incoming data, sleep the thread to save resources
while(in.available() == 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Store the incoming data in a string
String textIn = in.readUTF();
//Send it to all clients
sendAll(textIn);
}
//Close datastreams and socket to prevent memory leaks
in.close();
out.close();
sock.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Like you have done in the server side, you may use a separate thread to take care of incoming data in the client side. That way, the waiting for the user input in the console will not block the incoming data flow.
Here is an idea of how you could implement this.
New ClientConnection:
package client;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class ClientConnection extends Thread {
DataInputStream din = null;
public ClientConnection(Socket socket) throws IOException {
this.setName("Client-Thread");
this.din = new DataInputStream(socket.getInputStream());
}
public void run() {
boolean run = true;
while (run) {
// While there's nothing to read from the input stream, save resources
try {
// When there's incoming data, print it to the console
String reply = din.readUTF();
System.out.println(reply);
run = this.isAlive();
} catch (SocketException e) {
System.out.println("Disconnected");
run = false;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
din.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here is the reformulated Client:
package client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
// The socket for the client
Socket sock;
// The stream to send outgoing data
DataOutputStream dout;
public static void main(String[] args) {
// Create a new client
new Client();
}
public Client() {
try {
// Activate the socket to the host and port
sock = new Socket("localhost", 4444);
// Open the input and output streams
dout = new DataOutputStream(sock.getOutputStream());
//Listening for incoming messages
ClientConnection client = new ClientConnection(sock);
client.start();
// Start listening for user input
listenIn();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void listenIn() {
// Monitors the console for user input
Scanner userIn = new Scanner(System.in);
while (true) {
// While there is nothing left to read from the console
while (!userIn.hasNextLine()) {
try {
// Ensures resources aren't constantly being used by listening for input
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Get line from user input
String input = userIn.nextLine();
// if user exits the client, break the loop and exit the program
if (input.toLowerCase().equals("quit")) {
break;
}
try {
// outputs user input to Server
dout.writeUTF(input);
// Flushes all data out of the data output stream's buffer space
dout.flush();
} catch (IOException e) {
e.printStackTrace();
break;
}
}
// Close all the I/O streams and sockets, so there aren't memory leaks
try {
dout.close();
sock.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
On the server side, you may also consider removing the disconnected clients from the list of connections:
public class ServerConnection extends Thread {
...
public void run() {
try {
...
} catch (SocketException e) {
System.out.println("Client disconnected");
server.connections.remove(this);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I hope this helps.
I'm trying to send a stream of Strings from a Java server to a C++/CLI Client, but before doing that I wanted to start with the simplest case, i.e. send a single String from a Java Server to a C++/CLI client and display it.
The examples I found in the literature or in tutorials didn't work for me, knowing that the same Java Server communicated easily with another Java Client (either on the same machine or on different machines).
Without further ado, here's my Code:
the Java Server Side: SendStringToCpp.java
import java.net.*;
import java.io.*;
public class SendStringToCpp {
public static void main(String[] args) {
String message = "message"; // The String that contains the information
byte[] sentBytes = message.getBytes();
System.out.println("Message: " + message);
ServerSocket s = null;
try {
s = new ServerSocket(30011);
} catch (IOException e) {
e.printStackTrace();
}
Socket s1 = null;
try {
s1 = s.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OutputStream s1out = null;
try {
s1out = s1.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
DataOutputStream dos = new DataOutputStream (s1out);
try {
//dos.writeUTF(message); // Sending the String
dos.write(sentBytes); // Sending the bytes
} catch (IOException e) {
e.printStackTrace();
}
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s1out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s1.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The C++ Client Side: ReceiveStringFromJava.cpp
#include "stdafx.h"
#include <exception>
using namespace System;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Text;
using namespace System::IO;
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Creating the Socket...");
try {
//Socket^ listener = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp);
//Creates a UdpClient for reading incoming data.
UdpClient^ receivingUdpClient = gcnew UdpClient();
IPEndPoint^ RemoteIpEndPoint = gcnew IPEndPoint(IPAddress::Any, 30011);
//listener->Bind(RemoteIpEndPoint);
array <Byte>^ receiveBytes = receivingUdpClient->Receive(RemoteIpEndPoint); // get the Bytes array from the end poitn
String^ receivedString = Encoding::ASCII->GetString(receiveBytes); // retrieve the string from the received Bytes
Console::WriteLine("This is the message received {0}", receivedString);
// Console::WriteLine("this message was send from {0} on their ort number {1}", RemoteIpEndPoint->Address, RemoteIpEndPoint->Port);
}
catch (Exception^ e) {
Console::WriteLine("Error! ");
Console::WriteLine( e->ToString());
}
Console::ReadLine();
return 0;
}
And Here's the Exception printed on the Console:
http://i.stack.imgur.com/uTDqm.jpg
P.S. I tried to Bind the IPEndPoint to the Socket (it's commented above), but to no avail, and gave the same Error.
Socket^ listener = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp);
.
.
listener->Bind(RemoteIpEndPoint);
You need to use the UdpClient constructor that allows binding to a listening port.
Quoting MSDN (emphasis mine):
Initializes a new instance of the UdpClient class and binds it to the
local port number provided.
UdpClient^ receivingUdpClient = gcnew UdpClient(30011);
// specify the port both here ^^^^^ and here vvvvv
IPEndPoint^ RemoteIpEndPoint = gcnew IPEndPoint(IPAddress::Any, 30011);
array <Byte>^ receiveBytes = receivingUdpClient->Receive(RemoteIpEndPoint);
I'm making a Java program to make my computer a server to communicate with my smartphone over WiFi. Therefore I use the Socket class, as can be seen in the code below (based on Android-er):
package main;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerCommunication {
#SuppressWarnings("resource")
public static void main(String[] args){
ServerSocket serverSocket = null;
Socket clientSocket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
String message = null;
try {
int portNumber = 8888;
serverSocket = new ServerSocket(portNumber);
System.out.println("Listening :" + Integer.toString(portNumber));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true){
try {
clientSocket = serverSocket.accept();
dataInputStream = new DataInputStream(clientSocket.getInputStream());
dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("ip: " + clientSocket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
dataOutputStream.writeUTF("test");
message = dataInputStream.readUTF(); // <--- PROBLEM LINE
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if( clientSocket!= null){
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataInputStream!= null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataOutputStream!= null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
Everything works perfectly when the problem line (indicated with <---) is not present in the file. The message I receive is properly printed in the console. But form the moment I want to store this message in a String, I get a java.io.EOFException...
Can anyone tell me why I can print a message, but not store it as a string?
Thanks in advance!
The exception java.io.EOFException says that all the data in the stream is read, looks like you are trying to consume the data twice, one in the following statement,
System.out.println("message: " + dataInputStream.readUTF());
and the next one in,
dataInputStream.readUTF()
Either write more data from the writing side (client side) or consume once. Hope it helps.
Once you call
dataInputStream.readUTF();
it pops the string and you print that one. Then in the second call since there are no more data in outputstream the End Of File exception occurs.
You may try storing the popped string to a variable and then printing it:
String message = dataInputStream.readUTF();
System.out.println("message: " + message);
Remove your problem line
message = dataInputStream.readUTF(); // <--- PROBLEM LINE
I read through SO a lot and I found many examples which were doing what I am trying to do. But I just can't find the issue in my code at all. May be I just need a fresh set of eyes to look at my code.
So with risk of being flagged for duplicate thread here is goes. I have a simple Java code. It opens a port. Connects a socket to that. gets the inputstream and outputstream. Puts some text to output stream and inputstream tries to read the text. When the mehtod for readLine is executed it does not return back to the code. It just keeps running and never comes back to main method.
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
public class echoserver {
public static void main(String[] args) {
// TODO Auto-generated method stub
String hostName = "127.0.0.1";
// InetAddress.getLocalHost()
int portNumber = 5000;
ServerSocket ss = null;
Socket echoSocket = null;
try {
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber);
// echoSocket = ss.accept();
System.out.println("open");
System.out.println(echoSocket.isBound());
PrintWriter writer = new PrintWriter(echoSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
writer.flush();
// writer.close();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
String fromStream = is.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
BufferedReader reader = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
String fromReader = reader.readLine();
System.out.println(fromReader);
} catch (UnknownHostException ex1) {
// TODO Auto-generated catch block
System.out.println("EX1");
ex1.printStackTrace();
}
catch (IOException ex2) {
// TODO: handle exception
System.out.println("EX2");
ex2.printStackTrace();
}
finally {
try {
echoSocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
EDIT : Updated Code below... The only issue in this code is that while loop in Server.Run never ends. I looked for some other attributes (I remember something like isTextAvailable) but could not find it. The idea behind the code is to convert it into a chat client. needless to say its a struggle !
EDIT 2: I found the the issue. I never closed the socket from writer end so the listner kept on listening ! Thanks for help everyone !
clientsocket.close();
Added one line and it worked!
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.util.*;
public class echoserver {
static echoserver echo;
public static class Client implements Runnable {
Socket clientsocket;
String hostName = "127.0.0.1";
int portNumber = 5000;
static int onesleep = 0;
public void run(){
System.out.println("Client Run " + new Date());
try {
clientsocket = new Socket(hostName,portNumber);
PrintWriter writer = new PrintWriter(clientsocket.getOutputStream());
for (int i = 0; i < 10; i++) {
writer.println("test String " + i );
}
writer.flush();
clientsocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Server implements Runnable {
public void run(){
System.out.println("Server Run" + new Date());
int portNumber = 5000;
ServerSocket ss = null;
Socket serversocket = null;
InputStreamReader streamReader;
try {
ss = new ServerSocket(portNumber);
serversocket = ss.accept();
System.out.println("bufferreader read " + new Date());
streamReader = new InputStreamReader(serversocket.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
String fromReader;
System.out.println(reader.ready());
System.out.println(reader.readLine());
while ((fromReader = reader.readLine()) != null) {
System.out.println(fromReader);
}
System.out.println("After While in Server Run");
} catch (IOException ex_server) {
// TODO Auto-generated catch block
System.out.println("Server Run Error " + new Date());
ex_server.printStackTrace();
}
finally {
try {
serversocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("open" + new Date());
System.out.println(serversocket.isBound());
}
}
public void go(){
Server server = new Server();
Thread serverThread = new Thread(server);
serverThread.start();
Client client = new Client();
Thread clientThread = new Thread(client);
clientThread.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
echo = new echoserver();
echo.go();
}
}
I had prepared a version of this post earlier, but based on your last comment in the other answer, it seems you have already figured it out. I'll posting this anyways, in case it is of any help.
The broad answer is that your class, as you currently have it, effectively represents both the client-side AND server-side portions within the same thread / process. As you've seen, you're able to write your data to the outbound (or client-side) socket, but the server-side component never gets a chance to listen for incoming connections.
Consequently, when you attempt to read data from the inbound (or server-side) socket's input stream, nothing exists because nothing was received. The readline() method ultimately blocks until data is available, which is why your program seems to hold at that point. Additionally, like haifzhan said, creating a new socket using new Socket(...) doesn't establish the connection, all you have is a socket with nothing in the stream.
The ServerSocket#accept method what you need to use in order to listen for connections. This method will create the socket for you, from which you can attempt to read from its stream. Like haifzhan said, that method blocks until a connection is established, which is ultimately why it cannot function properly in a single-threaded environment.
To do this within the same application, you'll simply need to separate the components and run them in separate threads. Try something like the following:
public class EchoClient {
public static void main(String[] args) throws InterruptedException {
new Thread(new EchoServer()).start(); // start up the server thread
String hostName = "localhost";
int portNumber = 5000;
try {
Socket outboundSocket = new Socket(hostName, portNumber);
System.out.println("Echo client is about to send data to the server...");
PrintWriter writer = new PrintWriter(outboundSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
System.out.println("Data has been sent");
writer.flush();
outboundSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the server component, which operates as a separate thread:
public class EchoServer implements Runnable {
public void run(){
try {
ServerSocket ss = new ServerSocket(5000);
System.out.println("Waiting for connection...");
Socket inboundSocket = ss.accept();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(inboundSocket.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String fromStream = reader.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You did not connect to any client side socket...
From Writing the Server Side of a socket:
The accept method waits until a client starts up and requests a
connection on the host and port of this server. When a connection is
requested and successfully established, the accept method returns a
new Socket object which is bound to the same local port and has its
remote address and remote port set to that of the client. The server
can communicate with the client over this new Socket and continue to
listen for client connection requests on the original ServerSocket.
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber)
// echoSocket = ss.accept();
You should not use new Socket(host, port) to create a echoSocket, the ss.accept() is the correct way to establish the server client connection.
The reason it hangs because your code above(echoSocekt = ss.accept();) is not correct so the following will not be availalbe
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
If you invoke is.available(), it will return 0 which means 0 bytes can be read from.
Read the link I provided, check EchoServer.java and EchoClient.java, and you will estiblish your own connection