I have a problem that I can't send text to ChatServer. My code:
...
try {
socket.connect(address);
System.out.println("Successfully connected to server!");
Thread fromServerToConsole = new TelnetThread(socket.getInputStream(), System.out);
Thread fromConsoleToServer = new TelnetThread(System.in, socket.getOutputStream());
fromConsoleToServer.setDaemon(true);
fromServerToConsole.start();
fromConsoleToServer.start();
fromServerToConsole.join();
socket.close();
} catch() ...
Where in this try block should I put something like socket.getOutputStream().write("mystring".bytes()) if I want to send this text "mystring" to the SocketServer after connecting to it?
I tried to put this everywhere and it always didn't work, to send "mystring" I always had to press Enter in console of this client (console is for sending messages from console to the server). And the "mystring" was also printed to client's console, but it has to be printed only on the server's side.
I need to send "mystring" not from console, but automatically after connecting socket to the server.
Please help. Thanks.
You should try to flush() the stream after writing, it may help.
As far as i know, telnet sends every singly received bytes back as an echo, so if you don't want to display your echo, you should retrieve the inputstream of the connection, and drop all the echoes manually.
It seems like you are overdoing it a bit. I would recommend a simpler and more efficient method that doesn't have as much overhead, such as using a plain socket.
Client Snippet:
public static void main(String[] args) {
String ip = "Your IP/Hostname";
//set your port
int port = 7391;
Socket s = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
s.writeUTF("String To Write To SocketServer");
s.flush();
out.close();
s.close();
}
Server Snippet:
public static void main(String[] args) {
ServerSocket s = new ServerSocket(7391);
while (true) {
new SocketWorker(s.accept()).start();
}
}
public static class SocketWorker extends Thread {
Socket s;
public SocketWorker(Socket s) {
this.s = s;
}
#Override
public void run() {
DataInputStream in = new DataInputStream(new BufferedInputStream(s.getInputStream()));
//Receive String sent via the client
String response = in.readUTF();
in.close();
s.close();
}
}
Hopefully this helps!
Edit: You will also have to handle Exceptions. I didn't add any handling obviously.
Related
I have a server and a client set up in this way. I can't find the cause of the EOFException, because it happens randomly. It throws the following exception every time a client connects, but I can't figure out the source of it. It always occurs before it reads what the client has sent. The exception always is at this line:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Here is the exception:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End$3.run(End.java:62)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
Here is my server code:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
Here is my client code:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
What I've Tried
I've tried to fix this issue many times before. I tried to create object output streams. I've switched the order that I initialize the object input stream and object output stream. This is so that the server doesn't get frozen in a deadlock with the client. I have no idea what could be causing this error.
I think I know what is going on here, but I can't be certain because your code is fragmentary, and the symptoms are not well characterized. (The exceptions are unlikely to really be random, for example.)
First there is one indisputable fact. A one side of a connection sees an EOFException because the other side has closed the network connection. That's what that exception means.
In your case, the server gets the exception in the ObjectInputStream constructor because the constructor attempts to read an object stream header that the client side never sends ... on that connection.
Now, the theory. I think I know why. Here is the relevant part of your code (with some bits snipped out for brevity).
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
Notice that there are two sockets! The first one is created and passed to the shutdown hook. The second one is created and used within send and then closed.
I think the problem is the first Socket. When that is created, it establishes a connection to the server. The server code will accept it and then attempt to read. The read will block ... since the client side hasn't written anything to that socket. The client will then call send which opens and uses a different Socket.
Eventually, the client application exits.
When it exits, the shutdown hook closes the first socket. That causes the server side to see the end of stream ... and triggers the EOFException.
So how to fix this?
It rather depends on the "big picture". Is the real client sending a single message to the server, or does it need to reuse the socket to send multiple messages?
Assuming the former, the solution is simple:
Get rid of the code that creates a socket and passes it to a shutdown hook. As you have written it, it serves no useful purpose.
Rewrite the send method to use try with resources; e.g.
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
Note that the above will automatically close the 3 resources in the correct order.
I started to study java last month, and now I'm trying to write a simple chat program but I encountered something strange, and I was curious for the reason behind it.
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
String text = "";
ServerSocket ss = new ServerSocket(21025);
while (true){
System.out.println("Waiting...");
Socket s1 = ss.accept();
System.out.println("Connection accepted from "+s1.getInetAddress());
PrintStream pout = new PrintStream(s1.getOutputStream());
pout.println("Connected to the server");
new Thread(new Ricevitore(s1)).start();
}
}
}
public class Ricevitore implements Runnable {
String text = "";
Socket skt;
public Ricevitore(Socket skt){
this.skt = skt;
}
#Override
public void run() {
while (!text.equalsIgnoreCase("end")) {
try {
InputStream in = skt.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
text = br.readLine();
if (!text.equalsIgnoreCase("end"))
System.out.println(text);
}
catch (IOException e){}
}
}
}
public class Client {
public static void main(String[] args) throws IOException {
//Create a socket
try (Socket s = new Socket("127.0.0.1", 21025)) {
String text="";
while(!text.equalsIgnoreCase("end")) {
//Allows messages from server
InputStream in = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
if (br.ready()) {
Scanner server = new Scanner(br);
String testoServer = br.readLine();
System.out.println(testoServer);
}
//Allows to send text to the server
OutputStream out = s.getOutputStream();
PrintStream pout = new PrintStream(out);
Scanner tastiera = new Scanner(System.in);
text = tastiera.nextLine();
pout.println(text);
}
}
}
}
This is the complete program for the moment, my question is this: Since I wanted to avoid printing the word "end" to close the program, I inserted
if (!text.equalsIgnoreCase("end"))
but after that the server does not display the message "connected to server" unless I first input something through the client.
If I comment out that if statement, both messages "Connection accepted" and "Connected to server" got printed at the same time as intended.
I don't know if my question is clear, and I'm rather interested in learning why something like this happens.
If there are other things which any of you think is wrong I'll be happy to here about them.
I have only a wild guess which looks probable though.
In your client you read the message from the server if br.ready() returns true. It may happen that this function returns false, and the client goes to waiting for user's input.
After you send a message from the client to the server, the client repeats the test and now gets the message from the server.
I cannot explain why removing if (!text.equalsIgnoreCase("end")) in server's code makes the issue go away. That line isn't even executed until you send a message from the client.
So I think it's just a coincidence. There are two processes involved, and the outcome depends on how fast code executes in either process.
I ran your example many times, and once I did not receive the greeting from the server even though the if above was in its place.
A general suggestion for your code: you don't need to create input/output streams as well as Scanner on each iteration, you should do it only once.
To end communication session, you can just close PrintStream in your client as soon as you receive end from user. Your server will get null from br.readLine(). At this point, you close br and complete run().
I am trying to send an object over a connection using Java. This is my client side code. The server receives the data the first time, but the second time is stuck at socket.accept(). Am i doing something wrong here? Thank you!
public class Client
{
public static void main(String args[])
{
try
{
Socket socket = new Socket("localhost", 40003);
ClientObject c = new ClientObject(socket);
c.init();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class ClientObject
{
Socket socket;
public ClientObject(Socket socket)
{
this.socket = socket;
}
public void init()
{
try
{
// computation
SendObject so = new SendObject(toSend1, toSend2, rand, username.length());
// send all of this
OutputStream o = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(o);
oos.writeObject(so);
o.flush();
InputStream i = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(i);
// works, data received from the server
so = (SendObject)ois.readObject();
// further computation
so = new SendObject(null, digest, rand + 1, -1);
oos.reset();
oos.writeObject(so);
// doesn't work :(
o.flush();
}
}
Two things:
Flush the ObjectOutputStream instead of the underlying OutputStream.
The client it's using the same stream and thus the same connection to write to the server, hence the server should not expect a second accept but rather keep reading the stream of the same connection. You can of course also set up a new connect (Socket) and send the second object over that socket. Then the server should accept another socket.
Looks for me, that the server has successfully accepted the connection, otherwise you would not be able to send and receive. Look at your server code the problem may be that you close() the socket connection after the server has received from the client. Pleas provide your server code to have a look at.
I am trying to improve the speed at which the sockets transfer information but i am unsure how to do so. the pourpose of the code is to transfer a number, the date, and a short xml which is being sent in the form of a string.
this is the server code
import java.net.*;
import java.io.*;
public class SSocket extends Thread
{
private ServerSocket serverSocket;
public SSocket(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(100000);
}
public void run()
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
while(true)
{
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
int cor=in.readInt();
int i=0;
String transaccion = in.readUTF();
String fecha = in.readUTF();
System.out.println(cor);
System.out.println(transaccion);
System.out.println(fecha);
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
if(transaccion!=null && fecha != null && cor>0){
out.writeInt(cor);
}
else {
out.writeInt(-1);
}
if (i==100){
out.flush();
i=0;
}
i++;
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 1337;
try
{
Thread t = new SSocket(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
the code for the client is
import java.net.*;
import java.io.*;
public class ClientSocket
{
public static void send(int correl, String transaccion, String fecha)
{
String serverName = "localhost";
int port = 1337;
try
{
Socket client = new Socket(serverName, port);
int i=0;
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
out.writeInt(correl);
out.writeUTF(transaccion);
out.writeUTF(fecha);
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
int corin=in.readInt();
if(corin>0){
Envio.updater(corin);
}
else {
}
if (i==100){
out.flush();
i=0;
}
i++;
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
i have done some reading on the mater and it seems that posible solutions are to use either a buffer or swich to a datagram. however my experience on working with sockets is rather limited and i am unsure which would be best to use for this situation or if there is another option i havent yet considered. this code will be moving many transactions and i wish to do it in as short time as posible.
thanks in advance
ps. sorry for my bad english it is not my first language
Datagrams imply UDP, which is an unreliable delivery protocol so you're not guaranteed to get all content. That's probably not what you want; I'd stay with plain Sockets (which use TCP, which has reliable delivery).
Will the same client be calling send() repeatedly and connecting to the same server each time? That is, will there be many messages going across a single connection, or will each message be to a different server, with only a single message (or only a few) going to each of the many servers? If there's just one server that a client is going to connect to and if a given client is going to send lots of messages, you should keep the Socket open between send() calls; setting up and tearing down Sockets is expensive, so you're paying a high price for making a new connection each time.
Also, your server appears to only be able to handle a single connection at a time: you accept a connection, read from it, and then close it and accept a new one. So to make this work for more than one client, you'll need to separate the logic for accepting connections onto a different thread from the logic that reads data. If you'll only have a few clients at a time, you can just start a new thread to read from each socket as you create it for a new client; if you'll have lots of clients (thousands), you'll probably need to look at NIO for its ability to service multiple sockets from a single thread. But I suspect you're a long way from having that problem, if you ever do, so I'd just spawn a new thread for each socket.
Given the following code:
Client c1 = new Client();
c1.connect("127.0.0.1",1300);
Connect function:
public void connect(String serverName, int port)
{
try {
Socket socket = new Socket(serverName,port);
connection = new ConnectionProxy(socket);
connection.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
(ConnectionProxy class extends Thread) :
public class ConnectionProxy extends Thread {
private Socket socket;
private InputStream is;
private OutputStream os;
private StringConsumer client;
public ConnectionProxy(Socket socket)
{
this.socket = socket;
try {
is = socket.getInputStream();
os = socket.getOutputStream();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void run () {
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(os);
while (socket != null)
{
try {
String msg = dis.readUTF();
System.out.println(msg);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
I'm trying to implement a chat and I'm finding it difficult to send a message written by a client to all of the currently connected clients.
How could I do that? Should I hold the reference for each object (like c1) on the server side, or should I hold that ConnectionProxy thread on the server side?
If not, how do I implement that correctly and efficiently?
Would love to get some help!
Thanks!
Without being given much code, I'll outline what you'd want to do to achieve your goal.
On your server:
Keep an array or something similar of all connected client objects
Implement a send() function in your client class
Implement a broadcast() function that loops through the client list and sends each of them the message (using the aforementioned send() function
Make sure to keep track of (and remove) any dead/disconnected clients from your list, otherwise you'll run into trouble trying to send to them.
On your client:
Make sure you send a "connection terminated" message when you close/disconnect to tell the server you're leaving (makes it easier for the server to remove you)
The server should create a new client handler thread for each incoming connection.
For example, on the server side try something like:
ServerSocket server = new ServerSocket(port);
while (true) {
Socket client = server.accept();
//add incoming client to connected clients vector.
HandleClient c = new HandleClient(client);
clients.add(c);
}
After creating and storing clients in your vector of clients, you can the implement on the HandleClient class run() method a bufferReader (again not a must) to get your client text