Java DatagramSocket freezes on initialization - java

I'm writing a piece of UDP networking program (client - server), and I've run into some trouble.
I want to use streams to I/O data, so I googled "udp inputstream" and found UDPInputStream and UDPOutputStream. When I try to use these, however, the program gets stuck when trying to initialize the UDPOutputStream.
This is the line in my code that freezes:
outStream = new UDPOutputStream(InetAddress.getByName("127.0.0.1"), port);
System.out.println("UDP output stream initialized."); // <-- doesn't get called
I checked out the source of the UDPOutputStream, the code gets stuck on this line:
dsock = new DatagramSocket();
Why does the execution hang up on this line? On the server side, I still use my "old", non-stream version of a simple UDP code, and it works. The socket is initialized the same way and it doesn't hang up. I tried to put a port number to the initialization, but it doesn't solve the problem.

Host machines have more than one network interface (for example, 127.0.0.1 for the loopback interface and some other address for the network card; there may be more than one network card).
If you bind to the loopback address 127.0.0.1 then you'll only be able to receive packets sent locally. If want to receive packets sent over the network from a remote machine you must bind to the local IP address (e.g. 192.168.1.100).
Try following:
InetAddress addr = InetAddress.InetAddress.getLocalHost();
outStream = new UDPOutputStream(addr, port);

Related

Basic principles of a UDP server with multiple clients

I'm implementing a FTP program using UDP in Java (TCP is not an option), but I'm having trouble grasping the basics of how it's supposed to work.
As I understand, it's connectionless, so I should just have one server thread running which processes every request by any client.
Where I'm getting confused is during the actual file transfer. If the server is in the middle of a loop sending datagrams containing bits of a requested file to the client, and is waiting for an ACK from the client, but instead of that receives a completely different request from a different client, how am I supposed to handle that?
I know I could jump out of the loop to handle it, but then if the initial expected packet finally arrives, how can I pick up where I left off?
A UDP server works similar to a TCP in many respects. The major difference is that you will not receive a acknowledgement that your packets were received. You still have to know which client you are sending to, so use the DatagramSocket class. This is the Oracle tutorial for UDP: http://docs.oracle.com/javase/tutorial/networking/datagrams/index.html. It has a pretty good example in it. The significant part is getting the address and port of the original client, and returning your packets to that client:
InetAddress address = packet.getAddress();
int port = packet.getPort();
new DatagramPacket(buf, buf.length, address, port);
You could start a new thread on the server side for sending the bits every time a client sends a request. The thread would save the return address and port of the client, and die when the file send was done.

Sockets in Java...?

I need to build an application which can receive data from over a network and use this data to do some unrelevant things with.
Here's a piece of code to make clear what I'm doing.
On the server side:
static Socket client = null;
static ServerSocket ss = null;
if (ss != null) {
ss.close();
}
ss = new ServerSocket(5513);
isrunning = true;
System.out.println("Waiting for client...");
client = ss.accept();
System.out.println("Client accepted.");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
And the client side:
Socket client = null;
PrintWriter out = null;
try {
client = new Socket("hostname", 5513);
out = new PrintWriter(client.getOutputStream(), true);
}
Please note that this is just a piece of the code. There are no errors in the code.
After running the server-sided piece of code, it correctly waits for the client to connect.
Now here comes the problem. As soon as I try to connect from the client side, I'm getting a "connection refused"-error.
HOWEVER, I found something on the internet whoch told me to try telnetting from the client side. For example, let the server-sided IP be 192.168.1.1. So, after using this command:
telnet 192.168.1.1 5513
I actually get a connection with the server. The command will launch an empty screen, and everything I manually type in the command line will be sent to the server-side after pressing enter (checked with debugging).
So, I can manually connect to the server-side and send some data, but my code refuses to connect.
Anyone who knows what I am doing wrong?
Is this the code you're actually using?
client = new Socket("hostname", 5513);
Try changing it to:
client = new Socket("192.168.1.1", 5513);
client = new Socket("hostname", 5513);
Hostname needs to represent the IP Address you're connecting to. If you're trying to connect to yourself, it would be "localhost"
Also, the server is not listening for the client AT ALL TIMES, there must be a while loop so the server listens and accepts connections.
while (true) {
client = ss.accept();
out = new PrintWriter(client.getOutputStream(), true);
//You should probably assign it to a seperate thread to handle stuff for this client
}
And I should explain on why you're getting that particular error. When something says that the connection is refused, it usually means that the IP Address you want to connect to knows your sending a connection and is blocking it because it was not listening for that connection. Basically, when the server closed, you stopped listening for the client, so anything that came in on that port would be blocked. Of course, the other case could be that Java was blocked on your firewall and an exception should be made for it. Although this is rarely the case if what you're trying to accomplish is over a LAN.
You're not actually using "hostname" in your Socket object in the client are you?
It should the 192.168.1.1.
Are you on Windows? and If so have you added java.exe and javaw.exe to Firewall with inbound and outbound enabled? and have you added a rule for 5513 to your Firewall?
If yes Windows but no Firewall settings, that's your answer, open up your Firewall.

How to send datagram packet through Internet?

I'm trying to make a basic datagram client/server program with Java.
I've made the server cling to port 9321 on my local computer.
I've made the client on port 9320 on my local computer,
then send the data over wireless router network (192.168.1.100) at port 9321
the program works!
then i try to send the packet over (via router)internet IP 139.195.12.183(my ip) at port 9321
but it didnt work!
there is this exception:
java.net.SocketException: Interrupted function call: Datagram send failed
i've set the router to forward any request for port 9321 to my computer
and then i've set exception for the firewall on my computer on that port
this is the source
String SERVER = "139.195.12.183";
sendString(SERVER, 9321, "Greetings"); <<
private void sendString(String IP, int port, String toSend) {
byte[] buf = toSend.getBytes();
DatagramPacket packet = null;
try {
packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(SERVER), port);
ds.send(packet);<<
}catch(UnknownHostException e) {
System.out.println("unknownhostception");
}catch(IOException e) {
System.err.println("ioception "+e.getMessage());
}
}
i've had another answers from another forum it said:
"The way routers work, you can't see your external (WAN) internet address from your
internal network (LAN). If that's what you are trying to do, there's nothing wrong, it
just won't work.
Ian."
any explanation?
Some steps that you can take:
Check that the code works across two machines on your LAN.
Check that ping <target-ip> works on your machine.
If it does, check your local and LAN firewall settings for blocking on the port/protocol.
If the ports are unblocked change the port to something else. Some ISPs will block certain ports.
Some more reasons why this error could come up:
UDP (I Assume?) datagram too large.
Client side error that doesn't affect reception (Have seen similar things with some network stacks where the error was spurious.)
Post a link to your code from patsebin or something if you want more info.

Java socket blocks on connection to a server

I am trying to connect to server using a Java socket. I am trying to connect from port 80 to 90
int port;
Socket clientsocket;
String hostname = "www.google.com";
for(port = 80;port<=90; port++){
try{
clientsocket = new Socket(hostname,port);
System.out.println("Connection at port " + port + "\t" + clientsocket.isConnected());
clientsocket.close();
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
When I try to connect to any website like google.com or w3schools.com my program hangs on the socket() call for port numbers except 80.
Since those websites are not serving on ports 81-90 it should raise exception but instead it gets blocked. For port 80 it works fine.
When I try to connect to the apache server installed on my machine, it doesn't block for any port number and gives me Connection refused error which is the obvious behavior.
So why is it happening. Thanks in advance.
When I try to connect to any website like google.com or w3schools.com my program hangs on the socket() call for port numbers except 80. Since those websites are not serving on ports 81-90 it should raise exception but instead it gets blocked.
This is almost certainly not Java's doing.
When you invoke the Socket(String, int) constructor, the JVM asks the OS to attempt to establish a connection to the IP address corresponding to the supplied name, using the supplied port number. Assuming that we're talking TCP/IP, the OS sends off a TCP 'SYN' message, and waits for a response:
If the response is a 'SYN-ACK', it proceeds to establish the connection as per the protocol; see http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment.
If the response is an 'RST' (reset), the connect fails and this results in a Java "connection refused" exception. (This is typically what happens if the 'SYN' makes it to the remote server, only to discover that there is no application "listening" on the port you tried to connect on.)
If the response is an ICMP message of some kind (e.g. ICMP destination unreachable), this typically results in an immediate failure of the connection request, and a Java exception.
If there is no response, the OS tries again, and again, and again. Depending on the Java default connect timeout (or the explicit timeout), this process could continue for a long time.
So what is most likely happening is that something is filtering the 'SYN' messages on funky ports, and simply throwing them away. It could be the local firewall software on your PC, firewall software in your gateway, or your ISP's network, or software in the remote system you are attempting to talk to. Or this could be happening to the 'SYN-ACK' message coming back.
Either way, the blocking / timeout behavior is inherent to TCP/IP networking, and it is impossible to accurately diagnose at either the OS or Java levels. You simply need to adjust your expectations. (Or set a shorter connect timeout ...)
For this case, and any case:
/**
* Create end point and initialize connection with custom timeout for refused or server offline
*/
try{
InetSocketAddress endPoint = new InetSocketAddress(serverAddress, portNumber);
Socket socket = new Socket();
socket.connect(endPoint, 10000);
} catch(Exception e){
//... Handle connection error
}

MulticastSocket: Socket operation on non socket

I have some code like this:
InetAddress bind = InetAddress.getByName("192.168.0.1")
MulticastSocket socket = new MulticastSocket(new InetSocketAddress(bind,0));
socket.setInterface(bind);
On windows 7 and windows XP with JDK6u17,I got a SocketException: Socket operation on non socket.
But if I change the line 2 to :
MulticastSocket socket = new MulticastSocket(0);
It's ok, and works find too with jdk6u14.
Why? thanks.
EDIT:
Why port 0 should be the matter?
MulticastSocket socket = new MulticastSocket(0);
Everything goes well with this code.But not
MulticastSocket socket = new MulticastSocket(new InetSocketAddress(bind,port));
Whatever the port is.
As you are binding to a specific interface, calling setInterface() to the same interface is redundant. Remove it. It's only needed when you bind to INADDR_ANY, or in Java an InetAddress of null (or unspecified as a parameter).
To address errors in some of the other answers, and their implications:
Port zero is legal. It means a system-assigned port.
You only need a MulticastSocket for receiving multicasts. For sending, you can just use a DatagramSocket.
If the multicast interface needs to be specified, which it doesn't in this case, it can be done either via MulticastSocket.setInterface() or when calling joinGroup() or leaveGroup(). The latter option gives you granularity at the group level, but both techniques work. That's why they're both provided.
If you don't bind to a specific interface you should definitely call setInterface(). If you are on a multi-homed host you must to call joinGroup()/leaveGroup() once per interface, if you want to receive via all of them.
And a question: is 192.168.0.1 an IP address of an NIC on the local machine? It needs to be.
According to the documentation, you are supposed to instantiate it with a port number (thus 0 would be valid).
I am not so sure.
What's the constructor MulticastSocket(SocketAddress bindaddr) for.
And why it works fine with jdk6u14,but not jdk6u17?
And why it ok on windows 2003 server with jdk6u17?
On RHEL5.2 jdk1.4+
http://www.sockets.com/err_lst1.htm
Berkeley description: An operation was attempted on something that is not a socket. The specified socket parameter refers to a file, not a socket.
WinSock description: Same as Berkeley. The socket input parameter is not a valid socket handle (either it never was valid, it's a file handle (not a socket handle), or if it was a socket handle, it has been closed).
Detailed description:
select(): fails with WSAENOTSOCK if any socket in an fd_set is an invalid socket handle.
Developer suggestions: Did you close a socket inadvertently in one part of an application without keeping another part notified? Use socket state in an application and/or handle this error gracefully as a non-fatal error.
when the MulticastSocket created,socket.isClosed()==true
I haven't used these classes before, but the Exception occurs on line 3 when you call the setInterface method.
I would guess it's something to the effect that you're using the same reference twice or something.
I found a snippet of code that looked like this, maybe this is how you should be doing it:
MulticastSocket ms = new MulticastSocket(new InetSocketAddress(0));
ms.setInterface(InetAddress.getByName("192.168.0.1"));
You should first create the Multicast socket with a well known port - something higher than 1024 and less than 65535 - as already stated 0 means the operating system will choose a port for you (but then its going to be kinda random - which I guess you don't want).
For multicast - you generally need to set the interface to use on joinGroup() not on creation - e.g:
MulticastSocket socket = new MulticastSocket(2121);
InetSocketAddress socketAddress = new InetSocketAddress("localhost", 2121);
if (networkInterfaceName != null){
NetworkInterface ni = NetworkInterface.getByName(networkInterfaceName);
socket.joinGroup(this.socketAddress, ni);
}else {
socket.joinGroup(socketAddress.getAddress());
}
According to the MulticastSocket documentation you should use
Class D IP addresses in the range
224.0.0.0 to 239.255.255.255, inclusive
to bind a MulticastSocket. Apparently, the "192.168.0.1" is out of the multicast range.

Categories