I'm converting a working single player game to run across a network.
It's a simple game that runs on a terminal.. it's just text in / text out with the program.
It has a few classes, most of which print to System.out or System.err
but I want to send these messages to the client instead of printing them on the server system.
How can I do this, when the socket i/o is made in the main thread of one class?
Basically how do I access this from the other classes?
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(45444);
} catch (IOException e) {
System.err.println("Could not listen on port: 45444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String inputLine;
String outputLine;
You can use System.setOut() and System.setErr() to redirect STDOUT and STDERR to arbitrary output streams (in your case, a network I/O stream).
Related
I've created a single threaded server but turn around times are slow when processing multiple requests, how would i implement multithreading into this? I've attempted a few ways but it tehy alwasy have issues such as only being able to accept a single client or only taking commands from the first client that joined the server.
`
import java.net.*;
import java.io.*;
public class SocketServer {
public static void main(String[] args) {
if (args.length < 1)
return; // minimum length
int port = Integer.parseInt(args[0]); // set port
SocketServer.start(port);
}
public static void start(int port) {
// initialize server sockets and accept connection
try (ServerSocket serverSocket = new ServerSocket(port);) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
// read data from client
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); // buffered reader for strings
// send data to client
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true); // sends data in text format, the true in autoflush
// clears data after each call
String text;
//
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
// close
System.out.println("Connection Terminated.");
socket.close(); // closes connection with client
serverSocket.close();
}
} catch (IOException ex) // catch server exception and prints it
{
System.out.println("Encountered an exception, connection terminated.");
} catch (NullPointerException e) {
System.out.println("Encountered an exception, connection terminated.");
}
}
}
`
I am having problem even with this very basic client-server application. The client is not sending data/ the server is not receiving. I cannot understand where is the problem. I am even starting to think that i did not understand anything about sockets.
This is the Server code:
public class Server
{
public static void main(String args[])
{
try{
ServerSocket serverSocket = new ServerSocket(3000);
Socket socket = serverSocket.accept();
System.out.println("Client connected: "+socket.getInetAddress.toString());
Scanner scanner = new Scanner(socket.getInputStream());
while(true)
{
System.out.println(scanner.nextLine());
}
}catch(IOException e)
{
System.out.println("error");
}
}
}
This is the client code:
public class Client
{
public static void main(String args[])
{
Socket socket;
PrintWriter printWriter;
try {
socket = new Socket("127.0.0.1", 3000);
printWriter = new PrintWriter(socket.getOutputStream(), true);
while(true)
{
printWriter.write("frejwnnnnnnnnnnnnnnnnnnnnnnnnosfmxdawehtcielwhctowhg,vort,hyvorjtv,h");
printWriter.flush();
}
}catch(IOException e)
{
System.out.print("error\n");
}
}
}
If I run both on the same machine, the server prints correctly "client connected .....", but then prints no more.
What is the problem?
The server reads the next line. The client doesn't send any line ending. So the server can't possibly know that the line is supposed to be ended, and blocks until it finds an EOL in the stream. Or until the client closes its socket.
In client code, you decorate your output stream with PrintWriter, so you can use println.
Replace
printWriter.write("frejwnnnnn...rjtv,h");
printWriter.flush();
by:
printWriter.println("frejwnnnnn...rjtv,h");
Flush is useless since have request autoflush (true in PrintWriter constructor).
In server code, you can use a BuffererdReader decorator instead of Scanner:
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
while ((inputLine = br.readLine()) != null) {
System.out.println(inputLine);
}
Am I doing this right? When I try to run this on my computers loopback address I'm getting a "connection reset" error.
public class DateTimeClient {
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
String host = args[1];
try {
System.out.println("Connecting....\n");
Socket socket = new Socket(host, port);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
System.out.println("Date: " + reader.read());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class DateTimeServer {
public static void main(String[] args) {
int portNum = Integer.parseInt(args[0]);
try {
ServerSocket socket = new ServerSocket(portNum);
Socket client = socket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
client.getInputStream()));
PrintWriter writer = new PrintWriter(client.getOutputStream());
Date date = new Date();
writer.print(date.toString());
} catch(Exception e) {
e.printStackTrace();
}
}
}
I grab the port to run the server on, the port to connect to and the host as arguments in the main method, create sockets and use BufferedReader and PrintWriter. I followed Oracle's tutorial on this pretty closely so I'm not sure where I coulda made a mistake.
#EJP is correct, but I think that the actual problem is that the server side is neither closing or flushing writer. When the server exits, the TCP/IP connection gets closed (by the server-side OS) without any data having been written to the socket. The client side JVM sees a reset connection and throws an exception.
Solution: Close your streams properly on the server side and the client side should see the data. (Flushing would work too ... but if you neglect to close the streams in all cases, you risk problems with server-side file descriptor leaks. Hence, closing is the best solution.)
You're only reading one character, not a date. Try sending and receiving a line.
I am working on a web server (done), and thought I would make my own little text-based browser, the only problem is that I can't actually get the browser to read the responses. Here is the code:
import java.io.*;
import java.net.*;
class client
{
static Socket socket = null;
static BufferedReader in = null;
static PrintWriter out = null;
public static void main(String args[])
{
int fromServer;
try
{
socket = new Socket("localhost", 8001);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter( new BufferedOutputStream(socket.getOutputStream()));
out.println("GET /Library/WebServer/Documents/index.html.en HTTP/1.0");
out.flush();
while ((fromServer = in.read()) != -1)
{
System.out.write(fromServer);
System.out.flush();
}
}
catch (UnknownHostException e)
{
System.out.println("Unknown host");
}
catch (IOException e)
{
System.out.println("IO error");
}
}
}
You haven't completely finished the request. You need two newlines, as otherwise it just looks like you're still writing out the request headers.
Add an extra println and you may be okay, although as HTTP specifies CRLF for the line ending, I would actually use print rather than println, and put \r\n at the end of each line explicitly.
(I'd also avoid using PrintWriter, personally - swallowing exceptions is bad...)
i'm learning java and i faced some problems with sockets. I developed a simple client-server app - kind of knock-knock, it performs 4 steps:
client sends some message to server
server recieves them and saves to file
server sends back to client some other messages
client recieves them and also saves to file
Problem appears on step #4: client doesn't recieve messages and never gets out the loop:
while ((inStr = in.readLine()) != null) {
writer.println(inStr);
}
where in is type of BufferedReader:
try {
socket = new Socket(ipAddress, 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
On server side messages are sent:
try {
socket = srvSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
...
out.println("test from server #1");
out.println("test from server #2");
on client side i watched in.ready() - it returns false. On server side i watch out.checkError() - it returns true;
What am i doing wrong - why is the stream empty ?
Any help ia appreciated! :)
You are using public PrintWriter(OutputStream out, boolean autoFlush) which will flush automatically on new line or println. It does not autoflush after every write. You have to flush after every write.
Here is javadoc for the autoFlush param of the constructor:
A boolean; if true, the println, printf, or format methods will flush the output buffer
This might/might not solve your problem. But try keeping everything within Try Catch block. For eg: your ServerSocket initialization, writer blocks etc. If some error occurs, you might not be able to use writer anyhow, so there is no point in initializing it.
You might try writing to standard output stream for debugging instead of a file. Below code for Server/ Client is a minor variant of yours and its working.
Server:
Socket socket;
ServerSocket srvSocket;
BufferedReader in;
PrintWriter out;
try {
srvSocket=new ServerSocket(4444);
socket = srvSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("test from server #1");
out.println("test from server #2");
} catch (IOException e) {
e.printStackTrace();
}
Client
Socket socket;
BufferedReader in;
PrintWriter out;
String inStr;
try {
socket = new Socket("127.0.0.1", 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((inStr = in.readLine()) != null) {
System.out.println(inStr);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}