What Causes Port Mismatches ?

Started by
9 comments, last by JohnnyCode 9 years, 6 months ago

I am playing around with an object server , and have run onto an issue with the port

My client sends information on port 9999.

My server listens to port 9999.

However, whenever I receive an incoming connection,


System.out.println("" + socket.getRemoteSocketAddress() );

gives me an incrementing port number !

/127.0.0.1:56304
You said: Moo
/127.0.0.1:56305
You said: Baa
/127.0.0.1:56306
You said: Quack

Do you know what is causing this, and how to fix it ?

***

Client

***


public class Client {
	
	int port;
	String url;
	Socket socket;
	ObjectInputStream input;
	ObjectOutputStream output;
	
	public Client(String address,int po){url = address; port = po;}
	

	public void out(Object obj){
		try{
			socket = new Socket (url,port);
			output = new ObjectOutputStream (socket.getOutputStream());
			output.writeObject(obj);
			socket.close();
		}
		catch(Exception e){
			System.out.println("Client Crash\n" + e);
		}
	}
}

***

Server

***


public class Server implements Runnable {
	int port;
	ServerSocket ssocket;
	Socket socket ;
	ObjectInputStream input;
	Object dump;
	TestObj to;
	
	public Server(int por){port = por;}
	
	@Override
	public void run() {
		try{
			ssocket = new ServerSocket(port);
			
			while (true){
			socket = ssocket.accept();
			System.out.println("" + socket.getRemoteSocketAddress() );
			input = new ObjectInputStream(socket.getInputStream());
			dump = input.readObject() ;
			socket.close();
			to = (TestObj) dump;
			to.say();
				}

			 } 
		catch (Exception e){
			System.out.println("Server Crash\n" + e);
		}
		
	}
}

I cannot remember the books I've read any more than the meals I have eaten; even so, they have made me.

~ Ralph Waldo Emerson

Advertisement

So, first things first...

Creating and destroying a socket every time you want to send a message is a horrible idea. It's slow, and messy.

Secondly, there's no "port mismatch" here, the server is listening for connections on port 9999. In TCP the listening port does not accept messages. Instead it negotiates a connection which is given another port number to not get mixed up with the listening port.1

1 This is not perfectly accurate but serves reasonably well as a basic explanation of what is going on. For more information I highly suggest you buy a decent book on TCP/IP and networking in general.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

I think Washu's explanation is a little to over-simplified. It is actually the case that, if a server is listening on port 1234, and accepts a connection, packets through that connection do arrive on port 1234 (although at the API level, they will be routed to a socket other than the listening socket.)

In TCP, a connection is identified by a four-tuple: Destination IP, Destination Port, Source IP, Source Port.

When a client connects to a destination IP and port (like www.google.com:80,) the source IP is determined by the network address of the client, but the source port is generally randomly chosen by the kernel/network implementation on the client.

When one host extracts the "remote address" for a connection, it gets the IP/port of the other box. Thus, if "Destination" == "server," then the server will see Source IP, Source Port, and that port will be randomly allocated by the source. UNLESS the source binds the socket to a port before attempting to connect -- this is POSSIBLE, but it is pretty much always a bad idea. (For example, there's no guarantee that that port will be available on the host.)

There is another gnarl in the story: If the client (initiator of the ocnnection) is behind a NAT router, such as a typical cable modem or WiFi router, then the Source IP, Source Port that the client provides will be substituted by the router to some other Source IP, Source Port. However, the substitution will be made "back again" for returning traffic, so the client/server communication will still work.
enum Bool { True, False, FileNotFound };

So, first things first...

Creating and destroying a socket every time you want to send a message is a horrible idea. It's slow, and messy.

I have fought with this, however if I do not set the code up the way I have it, I get null pointer errors ...

This version gives null pointers


public class Client {
	
	int port;
	String url;
	Socket socket;
	ObjectInputStream input;
	ObjectOutputStream output;
	
	public Client(String address,int po){
		url = address; 
		port = po;
		try {
			socket = new Socket (url,port);
		} 
		catch (Exception e) {
			System.out.println("Client Ini Crash\n" + e);
		}
	
	}
	public void out(Object obj){
		try{
			//socket = new Socket (url,port);
			output = new ObjectOutputStream (socket.getOutputStream());
			output.writeObject(obj);
			//socket.close();
		}
		catch(Exception e){
			System.out.println("Client Crash\n" + e);
		}
	}
}

I cannot remember the books I've read any more than the meals I have eaten; even so, they have made me.

~ Ralph Waldo Emerson

You don't need to recreate your ObjectOutputStream each time either. Just create it once, when you're connected.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

null pointer ...

I cannot remember the books I've read any more than the meals I have eaten; even so, they have made me.

~ Ralph Waldo Emerson

null pointer ...


Then you're doing something wrong.

You should only need to create the socket once, and you should only need to create one output and one input stream.
Also, if you use TCP, the socket needs to be either connected, or accepted, before you can communicate on it.
enum Bool { True, False, FileNotFound };

in the win32 c api you must initialize the WSAStartup before using socket connections, could it be a similar problem with Java?

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

Investigating and fixing something like a NullPointerException is Java 101 stuff. If you cannot do that, then I don't think it is time to be venturing into network programming. You need to focus instead on bringing your debugging skills up to speed first.

First hint: exceptions have stack traces.

Second hint: by default, the Java runtime will catch unchecked exceptions and log them *with* the stack trace

Third hint: do not catch exceptions unless you have some interesting error handling behaviour

Fourth hint: if the Java compiler is forcing you to handle an exception, but you don't want to handle it locally, either add it to the method signature or wrap it in a sub-class of RuntimeException.

It is definitely possible to write this code without getting these exceptions. This is simply a bug in your code.

When i was a graduate assistant in college i used this explanation to explain addresses and ports to students:

An IP address identifies a computer.

A port number identifies a running program.

The address:port you place in the socket() constructor tells your client program how to find the machine and program the server is running at.

The client must create a return address (clients ip address: and random unique port number) or else the server cant reach it.

The client's port number must be random or else you cant have more than once instance of it running- just like you cant have more than one instance of a server running because the port numbers would be the same.

Think about how lame it would be if you could only have 1 web browser open and connected to only 1 web server at a time. This is why clients by default use random ports.

The server must use a static known port or else the clients cant find the server.

Basically an IP address is a layer 3 (IP) address and a port number is a layer 4 (TCP or UDP) address.

A "socket" is basically a source (IP+port) + dest (IP+port).

There is not enough information to know why you have a null pointer.

Is socket.getOutputStream() returning null?

Is your socket still connected or is your server immediately closing connections after they are accepted?

Your server will need a loop that polls the socket until it closes itself (or your program logic wants it closed).

>>incoming untested tutorial server code that I typed up in 5 seconds...


 
class myserver
{
 
socket s_listener;
LinkedList<socket> s_clients;
 
myserver()
{
setup listeneing socket
}
 
bool handleClient( socket s )
{
 
any data to recv? (use nonblocking tests so one client doesnt stop the server)
is conn closed? if so return false
also, send some data to the client as needed here
}
 
void handleListener()
{
accept connections here, add new socket to linked list
}
 
void handleClients()
{
foreach loop on linked list of client sockets
each time calling handleClient()
if handleClient returns false, remove the socket from the list (after the loop! you will break the iterator if you remove something insdie the loop)
}
 
static void main()
{
 
myserver s = new myserver();
while(1)
{
s.handleListener();
s.handleClients();
}
}

This topic is closed to new replies.

Advertisement