I'm creating an application which will need to transmit data back and forth between multiple computers on a network. Because of the way the data is to be sent, the client computers will be running the socket server, and the coordinating computer will be running the client socket.
I've created simple classes which are simply intended to encapsulate reading from and writing to these sockets. However, instead of reading anything, the receiving socket simply outputs nothing. I have confirmed that both client and server have a connection.
In the following Server and Client classes, the Socket is made public for debugging purposes only.
public class Server {
public Socket client;
private DataInputStream inStr;
private PrintStream outStr;
public Server() throws UnknownHostException, IOException {this("localhost");}
public Server(String hostname) throws UnknownHostException, IOException {
client = new Socket(hostname, 23);
inStr = new DataInputStream(client.getInputStream());
outStr = new PrintStream(client.getOutputStream());
}
public void send(String data) {outStr.print(data); outStr.flush();}
public String recv() throws IOException {return inStr.readUTF();}
}
The following is my Client:
public class Client {
private ServerSocket serv;
public Socket servSock;
private DataInputStream inStr;
private PrintStream outStr;
public Client() throws IOException {
serv = new ServerSocket(23);
servSock = serv.accept();
inStr = new DataInputStream(servSock.getInputStream());
outStr = new PrintStream(servSock.getOutputStream());
}
public void send(String data) {outStr.print(data); outStr.flush();}
public String recv() throws IOException {return inStr.readUTF();}
}
The Client class is instantiated, and the program started. Then, in a separate program, the Server is instantiated and started:
Server s = new Server(); System.out.println(s.client.isConnected());
while(true) {System.out.println(s.recv()); Thread.sleep(200);}
Client c = new Client(); System.out.println(c.servSock.isConnected());
while(true) {c.send("Hello World!"); Thread.sleep(200);}
isConnected() returns true for both the Client and the Server.
What could be causing this? I've never had to use sockets before now.
DataInputStream.readUTF() expects the first two bytes to be the number of bytes to read, but PrintStream.print(String) will convert the string to bytes and write them as-is.
DataOutputStream.writeUTF(String) will write the length like readUTF() expects.
Related
Bare with me as it's been a while since I've been on here and I know there's format rules for questions. I have coded two java applications, both are pretty simple. One being a server and two being a client that connects to the server via socket. Now this works on my computer but when I have a buddy run on his computer it doesn't connect. I want the server to be able to run on my computer and anyone who has the client can connect.
The relevant code for the server:
public static void main(String[] args) throws IOException {
// write your code here
System.out.println("Server Running...");
int port = 1020, backlog = 5;
String ipAddress = "2552:548:41aa:c3f0:563c:hgj9:8ca2:b3aa";
ServerSocket serverSocket = new ServerSocket(port, backlog, InetAddress.getByName(ipAddress));
Server server = new Server(serverSocket);
server.startServer();
}
The relevant code for the client:
public class Client{
public String username;
private Socket socket = new Socket("2552:548:41aa:c3f0:563c:hgj9:8ca2:b3aa", 1020);
public BufferedReader bufferedReader;
public BufferedWriter bufferedWriter;
public ChatController chatController;
public Client(String username) throws IOException {
try {
this.username = username;
this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(username);
bufferedWriter.newLine();
bufferedWriter.flush();
listenForMessage();
} catch (IOException e) {
closeEverything(socket, bufferedReader, bufferedWriter);
}
}
Like I said, this works on my computer but the not when client is on a different computer. My thoughts are that the issue is on the client side, possibly not using an open port? Thank you in advance and let me know if I need to edit if it's not a proper question format.
I created a simple server and a client, but the server could not read anything that was sent from the client. I also add a print statement after I sent the string, but it cannot be printed either.
public class Server {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket clientSocket = serverSocket.accept();
System.out.println("accepting client at address " + clientSocket.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
String input = (String) in.readObject();
System.out.println(input);
out.writeObject("Received");
out.flush();
}
}
Below is the client, and I just want to send a string "?????does not send":
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Client client = new Client();
client.sentInfo();
}
private static class Client {
private ObjectInputStream objectInputStream;
private ObjectOutputStream objectOutputStream;
public Client() throws IOException {
Socket socket = new Socket("127.0.0.1", 6666);
this.objectInputStream = new ObjectInputStream(socket.getInputStream());
this.objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
}
public void sentInfo() throws IOException, ClassNotFoundException {
this.objectOutputStream.writeObject("?????does not send");
this.objectOutputStream.flush();
System.out.println("????????");
Message resp = (Message) this.objectInputStream.readObject();
System.out.println(resp.getMessage());
}
}
}
I tried something else, if I just use InputStream and use a buffer to read bytes, like this:
Server code
This is the client code: client code
The code in the two link above would work. However, it would not work if I tried to use ObjectInputStream:
This is the server: server
This is the client: client
This is the Message object I want to send: Message class
Can someone explain this for me please? Thanks!
To read Strings from a socket use something like this:
DataInputStream input = new DataInputStream(clientSocket.getInputStream());
String message = input.readUTF();
You can open multiple streams from a socket, so if you want to read something else that really needs the ObjectInputStream than it can be open as well. Don't forget to properly close the streams & sockets.
I'm working on an assignment where I have to make 3 programs, a client, a proxy, and a server. The client is supposed to send messages to the server by sending them to the proxy, which sends them to the server, and vice versa. The server waits for the proxy to connect to it, and the proxy waits for the client to connect to it, then the client sends a message to the proxy which gets sent to the server. When I compile them though, while the proxy gets the message fine, the serve gets an error.
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at Server.run(Server.java:18)
at Server.main(Server.java:8)
Here is the client code
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception{
Client serv = new Client();
serv.run();
}
public void run() throws Exception{
Socket sock = new Socket("localhost", 7777);
PrintStream ps = new PrintStream(sock.getOutputStream());
ps.println("Hello Server");
sock.close();
}
}
Here is the proxy,
import java.net.*;
import java.io.*;
public class Proxy {
public static void main (String[] args) throws Exception{
Proxy serv = new Proxy();
serv.run();
}
public void run() throws Exception{
ServerSocket ss = new ServerSocket(7777);
Socket sock = ss.accept();
InputStreamReader ir = new InputStreamReader(sock.getInputStream());
BufferedReader br = new BufferedReader(ir);
String message = "";
message = br.readLine();
System.out.println(message);
Socket sck = new Socket("localhost", 8888);
PrintStream ps = new PrintStream(sock.getOutputStream());
boolean waiting = true;
while(waiting){
if(message != null){
ps.println("Hey Server, Client says: " + message);
waiting = false;
}
}
sock.close();
}
}
and here is the server
import java.net.*;
import java.io.*;
public class Server {
public static void main (String[] args) throws Exception{
Server serv = new Server();
serv.run();
}
public void run() throws Exception{
ServerSocket ss = new ServerSocket(8888);
Socket sock = ss.accept();
InputStreamReader ir = new InputStreamReader(sock.getInputStream());
BufferedReader br = new BufferedReader(ir);
System.out.println(br.readLine());
sock.close();
ss.close();
}
}
Does anybody know what I'm doing wrong?
Look at your proxy. First the sock Socket represents the connection with the client, then the sck Socket represents the connection with the server. However, when you create your PrintStream ps to connect with the server, you are using sock.getOutputStream as opposed to sck.getOutputStream. You are telling it to send information back to the client, which does not have an open BufferedReader to interpret, nor an open Socket at that point. Attempting to write to a closed connection results in a connection reset exception.
Secondly (though this is not causing the error), your proxy while loop is all jacked up. If you examine it, it will obviously cycle through at least once because waiting is defaulted to true. Then, you are checking to see if message != null. In this case, message will never be null because the client is set to always send the same message, and only one message. Most importantly, however, if for whatever reason message was null, there is nothing in the while loop to change that -- it does not attempt to read the next value from br or anything, so you will simply be stuck in an infinite while loop.
I believe what you were looking for was this:
String message;
while((message = br.readLine()) != null){
ps.println("Hey server, Client says: " + message);
}
But as I said, a while loop is not necessary in this case because the client is set to send only one message anyways, so you can simply do this:
ps.println("Hey server, Client says: " + message);
... without any sort of looping.
Ok so basically I'm creating an online multiplayer tic tac toe game using sockets but I've run into some logic trouble in my client class. I need to have the client running but then be able to write and read in a separate method from where the socket, streams, etc are. I'm sure this is a very simple solution and I'm probably over thinking it, I've googled it and I just can't seem to wrap my brain around it.
Basically my final structure should be
public Client
{
Instantiate sockets/streams, etc here.
}
public void writeAndRead
{
Write and read here.
}
My current problem is I cannot call my writer from another method.
My code is as follows
import java.net.*;
import java.io.*;
public class Client
{
private String host;
private int port;
public Client(String host2, int port2) throws IOException
{
host = host2;
port = port2;
//Instantiate a stringbuffer to store the reply from the server.
StringBuffer instr = new StringBuffer();
//Stores the host string into a usable IP.
InetAddress address = InetAddress.getByName(host);
//Instantiate a socket with the given IP and port name.
Socket socket = new Socket(address, port);
//Instantiate a output stream to the socket.
BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream());
//Instantiate a writer for the output stream using standard encoding.
OutputStreamWriter writer = new OutputStreamWriter(stream, "US-ASCII");
//Instantiate an input stream to read in reply from server.
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
//Instantiate a reader to read and convert the stream, once again using standard encoding.
InputStreamReader reader = new InputStreamReader(inputStream, "US-ASCII");
//Create the string to send to server with a char to let the stream reader know when the stream is completed.
String process = "x" + (char) 0;
//Write the string to the output stream.
writer.write(process);
//Clear the output stream.
writer.flush();
//Int c reads the data from the input stream.
int c;
//Receive the message and print.
while ( (c = reader.read()) != 0)
instr.append( (char) c);
System.out.println("Message received from server: " + instr);
}
}
What you do is read the input stream from the socket on a separate Thread so you can read and write the same time without waiting for packets of information to be delivered first. For the writing to the socket you can put the in the Main Thread.
In a class it is usually a good idea to have some variables as private fields in you class and that your constructor is responsible the initial collection of and initialization of these variables.
So as you have
public Client(String host, int port) throws IOException
{
this.host = host;
this.port = port;
}
and then other methods will do one piece of work
e.g.
public void connect () {
//Stores the host string into a usable IP.
InetAddress address = InetAddress.getByName(host);
//Instantiate a socket with the given IP and port name.
this.socket = new Socket(address, port); // yes another field
}
and then other methods will do the reading and writing.
Also you may find that you need to use separate Threads, so try following a Chat example which you can easily find on the internet.
If I understand your question correctly, the variable writer should be a class variable instead of in the scope of the constructor for Client:
public class Client {
private OutputStreamWriter writer;
private String host;
private int port;
public Client(String host2, int port2) throws IOException
{
// ...
}
public void readAndWrite() {
// ...
writer.write();
}
}
I am currently trying to take an ArrayList and fill it with sockets using .add, when the socket is passed into the constructor. When i run the debug, it looks like there is only ever 1 socket filling the ArrayList, and no more, even though I've opened like 6 client threads.
Server class
public static void main(String[] args) throws IOException
{
final int PORT = 8888;
ServerSocket server = new ServerSocket(PORT);
System.out.println("Waiting...");
while(true)
{
Socket s = server.accept();
System.out.println("Client connected");
Service service = new Service(s);
Thread t = new Thread(service);
t.start();
}
Service class
public class Service implements Runnable
{
private Socket s;
private Scanner in;
private PrintWriter out;
private ArrayList<Socket> sockets = new ArrayList<Socket>();
public Service(Socket aSocket)
{
s = aSocket;
sockets.add(s);
}
It's because you create a new Service every loop => you will have 6 Service objects with one arrayList in each containing each objects socket. If you want your arrayList to contain all clients / sockets, you will have to have this list in your server class. Also it's rarely a good idea for your clients to know about all other clients.
I also suggest putting in a Thread.sleep(100) in your main method (server), otherwise it will take up a lot of your precessing power.
public static void main(String[] args) throws IOException
{
final int PORT = 8888;
ServerSocket server = new ServerSocket(PORT);
System.out.println("Waiting...");
private ArrayList<Socket> sockets = new ArrayList<Socket>();
while(true)
{
Thread.sleep(100);
Socket s = server.accept();
System.out.println("Client connected");
Service service = new Service(s);
Thread t = new Thread(service);
t.start();
sockets.add(s);
}