Stuck at socket.accept() - java

Hello I just started a Java Enterprise Edition class. This is my first exposure to this side of java programming so this is all pretty new to me. I was reading my textbook and decided to type it one of the codes given to me to try it out. This code is not mine. The program should output "hello, enter BYE to exit" and then echo back anything that is typed into the prompt. For some reason the code hangs at the try block containing s.accept (it outputs 1 then 2 then hangs). I was just wondering if anyone would have any insight as to why this isnt working for me when i copied it exactly from my textbook. Here is the code:
import java.io.*;
import java.net.*;
import java.util.*;
public class EchoServer
{
public static void main (String[] args) throws IOException
{
System.out.println("1");
try (ServerSocket s = new ServerSocket(8189))
{
System.out.println("2");
try(Socket incoming = s.accept())
{
System.out.println("3");
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
try(Scanner in = new Scanner(inStream))
{
PrintWriter out = new PrintWriter(outStream,true);
out.println("Hello! Enter BYE to exit.");
boolean done = false;
while(!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo: " + line);
if(line.trim().equals("BYE"))
done = true;
}
}
}
}
}
}
Im sure this is something relatively simple to explain, im just new to this and was wondering why this isnt working when i try to run it.

Is there a corresponding EchoClient demo in the textbook?
Socket.accept() hangs by design until a client connects to the port that is being waited on, in this case, port 8189. Your program is working fine

If you read the documentation you will see that Socket.accept() actually hangs the thread until a client connect , so after the connection is established it will continue also your using an echo protocol , so you need to make sure that the client in this case is ANOTHER server that supports echo protocol

You're dealing with networking. Great. Let's distinguish between terms a bit.
socket.accept() is an example of a blocking function call. I can't find any link to provide a quick interpretation but, to oversimplify, your code stops at that point until some event it is waiting for finally happens, in this case, a connection from a corresponding client. Hence, its behaving normally, as expected, as documented. You'll encounter lots of other blocking function calls waiting for all sorts of events like an item is inserted to a queue, threads finish processing, etc.
In contrast, the word "hang" as normally used, refers to a deadlock or (less commonly), kernel panic. This is usually a mistake on the programmer's part.

Related

How to communicate with a python Twisted server from Java successfully?

These questions may sound silly, but I am new to this networking thing.
I have been trying for quite a few days now to implement a client that works with a Twisted server, but I am failing to get any response back from the server. I have read a lot of docs and watched a few tutorials and I got some of the stuff fixed and got some of the concepts better understood.
Before I step on to asking any questions, I wanna show you my code first. This is what I use to talk to the Twisted-based server:
val socketfactory: SocketFactory = SocketFactory.getDefault()
val socket = socketfactory.createSocket(host, port)
socket.keepAlive = true
socket.tcpNoDelay = true
val isSocketConnected = socket.isConnected //this checks socket's connectivity
val dOut = DataOutputStream(socket.getOutputStream())
val dIn = DataInputStream(socket.getInputStream())
val teststring = "Hi server!"
dOut.writeUTF(teststring)
Log.d("MILESTONE", "MESSAGE SENT AT THIS POINT, Socket is connected ?: $isSocketConnected")
var testreader = ""
while (true) {
testreader = dIn.readUTF()
Log.d("READING:", "RECEIVED THIS: $testreader")
}
My code seems to never get to the second "Log" line. It never gets there. I assume that's because I never get any input from the server. This is getting me confused. Because "socket.isConnected" returns true. Doesn't that mean there is an ongoing connection between the client (me) and the server ? But when I send any output the server doesn't talk back.
So my questions are:
1- Am I doing something wrong? Why do I receive no talk from the server and it blocks the code?
2- Is SocketFactory necessary ?
3- Is there any library that communicates with Twisted from Java ?
Thanks in advance !
For everyone who's struggling to communicate with a Twisted-running python server, I came with the absolutely best solution ever! After inspecting Twisted's open source code, I came to realize it has a "LineReceiver" class that only responds to a message if the line is finished. In other words, you can keep sending data forever and it will never respond until you finish the line and start a new one. Twisted will know the line has finished when a delimiter is used. (It is configured on the server-side). Most servers running Twisted will use a line delimiter : "\r\n"
That's the tricky thing! Once you send that little string, it will start responding to you. Here it is in an example :
val dOut = DataOutputStream(socket.getOutputStream()) //This is my favorite way of sending data!
val dIn = socket.getInputStream().bufferedReader(Charsets.UTF_8) //This is my favorite way of reading data !
val teststring = "hi server! \r\n" //This is the tricky part !
That's it ! all you have to do after that is read the lines from the bufferedReader, like this !
var testreader: List<String>
while (true) {
testreader = dIn.bufferedReader(Charsets.UTF_8).readLines()
for (line in testreader)
Log.e("MILESTONE", line)
}
After I started reading the input, I found out the server started actually sending me strings and communicating back with me. I hope everyone will get their codes working concerning this or any other thing!

Java Socket Packet Interception

I'm trying to write a socket program in Java that intercepts data/packets.
I've successfully written this in python:
import socket
def createListener(port):
srvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
srvSock.bind(('localhost', port))
srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
while True:
raw_data, addr = srvSock.recvfrom(65536)
print('data: ' , raw_data)
createListener(80)
This is my basic Java socket program
public static void main(String[] args) {
try{
ServerSocket ss = new ServerSocket(80);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str = (String)dis.readUTF();
System.out.println("data: "+str);
ss.close();
} catch(IOException i){
System.out.println(i);
}
}
However, when run, it doesn't intercept all data moving through the port on the network like the python program does. Specifically this line srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) in the Python script enables the socket to listen to the port and capture/intercept the entirety of the data going through it.
I cannot find a Java alternative to this syntax or any solution to my problem at all for that matter.
I would appreciate any help in how to use sockets to intercept packets on a network port.
Thanks
Im fairly certain what you are trying to do cannot be done with Java. It looks like you are trying to use "promiscuous mode", but Java sockets cannot be started in promiscuous mode. Java sockets are an end-to-end implementation: they can't listen on the network port for all traffic. For sure the network port would have to be in promiscuous mode, but I don't think Java is the right choice for you.
The only thing I can think of that might get you there would be doing a native call in something like JNI, but I wouldn't even really know where to start with that.
Here is a really old post that I found that is kind of related: java socket and web programing
From the looks of it, you're trying to read incoming bytearrays as string lines.
If that is so, this is what I do to read lines without missing a single line (In Kotlin):
socket.getInputStream().bufferedReader(Charsets.UTF_8).forEachLine {
it -> { /* Do what you wanna do with the input */ }
}
In Java, it's much less abstract :
BufferedReader(InputStreamReader(socket.getInputStream(), Charsets.UTF_8), 8 * 1024)
Then, use lines from this buffered reader as a line sequence to read your incoming lines.

Connection reset by peer or socket closed out of nothing

So far I've used this site whenever I encountered a problem and I've found solutions too, but this time I have no idea what's even happening.
I am working on a game that is based on a 1-vs-1-multiplayer-mode. So far i have created a server and my program with the client.
My server creates a new thread with a socket for every client that connects with the server and when the "New Game"-Button is pressed in the game, the thread searches for another thread that is looking for a new game right now and once it found him, creates a separate thread that sends a message to both threads to signal them that a game has started, which is then sent through their socket to the program which reacts accordingly.
Here is my code:
Thread:
public void run() {
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
ServerNachricht inputLine, outputLine;
LabyrinthProtocol prot = new LabyrinthProtocol();
while (socket.isConnected()) {
ServerNachricht is a class that consists of a type(int), a sender(player) and a message(String).
When the thread gets a new game message, the protocol changes the players status-value to "searching", then looks if another "searching" player exists and then changes both players values to "playing" and returns a new ServerNachricht of type Kampfbeginn with the found player as sender.
After the protocol returns the outputLine, this is what the thread does:
if (outputLine.getArt() == ServerNachricht.KAMPFBEGINN) {
System.out.println(outputLine.getSender().getSname()+" ist da");
server.kampfbeginn(this, outputLine.getSender());
}
The sysout just verifies that the protocol has actually found another player and is printing that players name to be sure. So far, this has always worked.
Here are the parts that call for a new game in the server:
public void kampfbeginn(LabyrinthThread t, Spieler gegner) {
KampfThread kampf = null;
System.out.println(gegner.getSname()+" anerkannt");
for(int i = 0;i<threads.size();i++){
if(threads.get(i)!=null){
System.out.println(threads.get(i).getSpieler().getSname());
if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){
LabyrinthThread gegnert = threads.get(i);
kampf = new KampfThread(t,gegnert);
t.setKampf(kampf);
gegnert.setKampf(kampf);
break;
}
}
}
This code searches through every existing thread (the server stores them in a vector) and checks if that threads connected player is the player returned by the protocol. When the thread was found, both threads are then given to a newly created thread that stores both of them while also storing that new thread in both threads.
The new thread even verifies the connection with two sysouts:
public KampfThread(LabyrinthThread spieler1, LabyrinthThread spieler2) {
super();
this.spieler1 = spieler1;
this.spieler2 = spieler2;
System.out.println(spieler1.getSpieler().getSname() + "ist drin");
System.out.println(spieler2.getSpieler().getSname() + "ist drin");
}
which I also get every time.
After both connections are established, that thread sends a message to both threads so that they will notify their programs to start:
case(ServerNachricht.KAMPFBEGINN):
spieler1.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler2.getSpieler(),""));
spieler2.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler1.getSpieler(),""));
break;
which calls this method in the threads:
public void ThreadNachricht(ServerNachricht s) {
if(socket.isConnected()) {
try {
out.writeObject(s);
} catch (IOException e) {
e.printStackTrace();
}
}
The strange thing is that this works absolutely perfect about 80% of the time (so both programs go into the "game started" mode) but sometimes it just works for one or even neither program and the server gets either a
Connection reset by peer
or a
Socket closed
error in
public void ThreadNachricht(ServerNachricht s) {
if(socket.isConnected()) {
try {
out.writeObject(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
in the out.writeObject(s); line. There is no line anywhere that closes anything (I've even taken out every single close() out of anywhere to make sure that nothing can interfere) and there seems to be no pattern at all to when it works and when it doesn't (and not working closes the servers and the programs clientsocket so the program is unable to work when that happens). Is there any way I can guarantee that my program works or is there any error I made? I am rather desperate because I couldn't even do major tests to find out a pattern since starting the program twice with exactly the same setup still causes it to work most of the time.
Edit: I literally just had a situation in which one player went into the new game mode while the other one stayed in the main menu (resulting in a Connection reset by peer: socket write error for the server) twice in a row before it worked the third time without any problems in the same run. So I searched with both players but only one went into the game screen (and the other one got the error). I then pressed back to go into the main menu and did the same again with the same result. When I tried for the third time, it worked and both players got into the game screen and started interacting with each other.
It was actually a rather funny error I made: My server kept the threads stored in his vector even after their sockets disconnected. So logging in with an account that was already connected to the server before since its last restart (I use to keep the server running when I'm just testing cosmetic things) causes its
for(int i = 0;i<threads.size();i++){
if(threads.get(i)!=null){
System.out.println(threads.get(i).getSpieler().getSname());
if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){
loop to determine the thread for the other player to find an older and already closed thread and not the one the other player is connected to at the moment.
'connection reset' usually means that your wrote to a connection that had already been closed by the peer: in other words, an application protocol error.
'socket closed' means that you closed the socket and then continued to use it.
Neither of these comes 'out of nowhere'. Both indicate application bugs.
isConnected() is not an appropriate test. It doesn't magically become false when the peer disconnects. I'm not sure it becomes false even when you disconnect.
All this indicates nothing more than coding bugs. Post more of your code and I'll show you some more of them.

How to test connectivity to ports

I'm still a beginning programmer but I like to experiment and learn while practicing. I play League of Legends a lot, this is the biggest online game today. Sometimes the server of this game are offline and my idea was to make a java programm that checks wether the game is online (ports are open) and then tells me if the game is online or not. Due to me being a beginner programmer and my understanding of ports/network adresses still lack a bit, I wonder if someone could explain or help me achieving my goal. If it is by explaining or providing helpfull links, I'm open to everything!
Thanks in advance,
Boris
There are some tools that you can check that whether the server is alive or not.
The most basic one is ping in CMD:
ping stackoverflow.com (if you have domain)
or
ping 198.252.206.16 (if you have IP)
if you see sth like this so server is alive and give a response:
Ping statistics for 198.252.206.16:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 142ms, Maximum = 145ms, Average = 143ms
But if you see this, then server or your internet connection has a problem:
Request timed out.
There are some other tools such as Hercules to test a server alive or not.
If you are still sure to write a program yourself in java, you can try to create a new java.net.Socket. If that line throws any exception then you are not able to connect to the server. To manage this, you should use "try-catch" blocks.
You can use java socket to detect the port is alive or dead:
import java.io.IOException;
import java.net.Socket;
public class PortDetect {
public static void main(String[] args) {
try {
new Socket("1.2.3.4", 8080);
System.out.println("alive");
} catch (IOException e) {
e.printStackTrace();
System.out.println("dead");
}
}
}

Expanding my Java program to send a alert message to other computers

I've written a java intake program that send an PDF-formatted intake to a shared folder so that other people in the network can read it. However, there is not a way for the other people to know that an intake was sent unless someone tells them, so I want the program to send an alert message to the other computers telling them that an intake has been sent.
Now I've done some research into this and figured that TCP is the way to go since it's reliable. I also know that this is a one-to-many sending going on, so I assume that my Intake program will act as the server an the other computers will be the client, or should it be the other way around?
Now I assume that I have to create a client program that listens to the server and waits for it to send a message.
With that in mind, how do I:
Create a client program that listens for the message continuously until the program is closed. I assume that I'll be using "while (true)" and sleep. If so, how long do I put the program to sleep?
Make it as part of Windows service so that can load up when Windows start.
On the server end, how do I:
Send messages to more than one computer, since TCP is not capable of multicasting or broadcasting. I assume an array/vector will play a part here.
Oh, this is a one-way communication. The client doesn't have to respond back to the server.
First of all, UDP is quite reliable (in fact, as reliable as the IP protocol itself). TCP simply ensures that the data was received which involved quite a lot of magic in the back end. Unless you absolutely need to be sure that other machines got the message, you could do it with UDP. Mind that I'm not saying “Don't use TCP”, I just want to make it straight that you should take UDP into consideration as well.
Anyway, yes, you can create a simple listening program. Here is an example of a client in Java that reads messages from the server. It overrides the run method of a Thread class:
public void run() {
try {
String messageFromServer = reader.readLine();
while (messageFromServer != null) {
// Do things with messageFromServer here
// processor.processFromServer(messageFromServer);
messageFromServer = reader.readLine(); // Blocks the loop, waits for message
}
}
catch (IOException e) {
// Handle your exception
}
}
Amongst other things, my thread was set up as such:
public CommunicationThread(String hostname, int port, int timeout) throws IOException, SocketTimeoutException {
InetSocketAddress address = new InetSocketAddress(hostname, port);
socket = new Socket();
socket.connect(address, 2000); // 2000ms time out
// You can use the writer to write messages back out to the server
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Now, regards to server-side you can do something as follows:
Write a program to allow clients to contact, given that they know your address.
Accept the connections, and store the sockets in a list.
When you need to send out a message, traverse the list and send the data to everyone on it.
You can start listening on your server with
this.socket = new ServerSocket(port);
You could (or even should(?)) make it threaded so that you can accept clients while serving others. You can accept new clients with:
socket.accept(); // Blocks, waiting for someone to connect, returns open socket
Feel free to pass that to a whole new class which can deal with BufferedWriter (and maybe even BufferedReader if you want to read from clients as well). That class is where you would implement things such as writeToClient(message)
Consider the situation where you have a ClientConnection class that has writeToClient(String s) method and (Server server, Socket socket) and initialized ArrayList conList.
Here is how you would follow:
In a separate thread in Server, accept connections with
ClientConnection con = new ClientConnection(this, socket.accept());
conList.add(con);
Then, when you want to write to clients:
for (ClientConnection c : conList) {
c.writeToClient("I'm sending you a message!");
}
I hope you get a vague idea of what you need to do. Read the Socket documentation, it's very useful. Also, as always with threaded applications, make sure you aren't doing things such as modifying a list while traversing it and avoid race conditions.
Good luck!

Categories