Click to See Complete Forum and Search --> : Socket's won't work remotely.


tophat
February 20th, 2008, 09:46 PM
I have been working on a server/client program now for a few weeks, and they work flawlessly together by binding the client to 127.0.0.1, or the localhost. But, for some reason, the client/server cannot connect by having the client on one computer (ip address) and a server on another. Shouldn't this just automatically work, or is there something I'm missing? This definitely has something to do with either socket() (WSASocket()) or accept(), but I cannot distinguish what...

Here is the broken down version of the client (this is in a function, so client_ip and port variables are sent through the function, these work properly.):


WSAData wsdata;
WORD wsver = MAKEWORD(2, 0);
int startup = WSAStartup(wsver, &wsdata); implement

if(startup != 0){

std::cout << "Startup failed: " << WSAGetLastError();

WSACleanup();
return false;
}

std::cout << "Connected to " << connect_ip << ":" << port << "\n";

// SOCKET kSock = socket(AF_INET, SOCK_STREAM, 0); // not sure which, this or one underneath...

SOCKET kSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);

if(kSock == INVALID_SOCKET){
std::cout << "Socket init failed";
return -1;
}

std::cout << "Socket initialized\n";

sockaddr_in sin;
sin.sin_port = htons(port); //Connect to port 80
sin.sin_addr.s_addr = inet_addr(connect_ip.c_str()); //Connect to localhost INADDR_ANY
sin.sin_family = AF_INET;

if(connect(kSock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){

std::cout << "Connect failed, error: " << WSAGetLastError(); //Returns error code
WSACleanup(); //Cleanup the library
return false;
} else {
.... and so on ....


Server:


WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);

struct sockaddr_in server;
struct sockaddr_in client;

int sin_size;

if ((fd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == -1) {
cout << "Socket error...\n";
return false;
} else {
cout << "Socket intialized...\n";
}

server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;

memset(&(server.sin_zero), '/0', 8);

if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(BOOL)) < 0) {
cout << "Unbind error...\n";
} else {
cout << "Socket unbound...\n";
}

if (bind(fd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
cout << "Error Code: " << WSAGetLastError();
cout << "\nBind failed...\n";

return false;

} else {
cout << "Bind works...\n";
}

if (listen(fd, BACKLOG) == -1) { // BACKLOG SOMAXCONN

cout << WSAGetLastError();
cout << "\nListen failed...\n";

return false;

} else {
cout << "Listen works...\n";
}

sin_size = sizeof(struct sockaddr_in);

cout << "Waiting for client...\n";

if((fd2 = accept(fd, (struct sockaddr *)&client,&sin_size)) == -1) {

cout << "Error Code: " << WSAGetLastError();
cout << "\nAccept failed...\n";

return false;
} else {
cout << "Connection accepted...\n";
}

... goes on and on ....


again, this works by binding connecting as client to 127.0.0.1 on the chosen port, but this will not work if the programs are each on a different computer (ip). Any suggestions of what I am doing wrong?

Spasm
February 20th, 2008, 10:11 PM
I'll bet the problem isn't with your program. Is the computer that's acting as the server behind a router? If it is, you probably have to forward the port it's listening on. Otherwise, your router will receive a connection request, but it won't know what to do with it, so it will either deny or ignore it. When you forward the port, you're programming your router to send to connection request to a certain computer on the network. See http://portforward.com

tophat
February 21st, 2008, 10:35 AM
that actually makes a lot of sense that it would be the router. my computer is behind a rounter, so i'll try re-configuring it. But, is there some way this can be done with Win32 functions and c++?

MikeAThon
February 21st, 2008, 10:54 AM
I agree with Spasm. If the programs work when both the client and server are on a single machine, but don't when they are on separate machines, then the problem usually is with one of two things: firewalls and/or network architecture (routers, port forwarding etc).

First try the programs where both client and server use machines from the same local network (i.e., no router or switch in between). It's a simpler case. If the programs don't work in this case, then we can focus on the programs; otherwise, on firewalls and network architecture.

Mike

Spasm
February 21st, 2008, 11:45 AM
that actually makes a lot of sense that it would be the router. my computer is behind a rounter, so i'll try re-configuring it. But, is there some way this can be done with Win32 functions and c++?

If you mean configure your router to forward a port, then the Windows API can't help you here. Chances are you're going to have to go to http://192.168.1.1/ (or whatever your gateway is), and do it manually. I think you can forward the port automatically with UPnP (Universal Plug and Play), but I have no idea how that works ~_~

MikeAThon
February 21st, 2008, 01:37 PM
Looking at your code again, I see (from the comments) that the client is trying to connect to "localhost", which is wrong. That might work when both client and server are on the same machine, but it definitely will fail under all scenarios when the client and server are on separate machines.

You can confirm this failure by running client and server on separate machines from the same local network, as suggested above.

Your client needs to connect to the IP address of the server. I might be 192.168.1.100, but use IPCONFIG on the server to find out.

Mike

tophat
February 21st, 2008, 01:47 PM
That comment you were looking at was kind of old. I was just using 127.0.0.1 before to test, and that comment was just to remind me. Prior to the code for the client, there is a line which it prompts the user to type an ip address they wish to connect to, so it's not connecting to localhost, but rather the specific IP the user types in. I honestly believe it's having to do with the router and not knowing what to do with the port, so I guess I'll just have to manually change this.

MikeAThon
February 21st, 2008, 01:49 PM
OK, but I still recommend that you first make the test of running client and server on separate machines that are on the same local network, just to be sure.

Mike

tophat
February 21st, 2008, 07:56 PM
ugh, i just tried using the client and server on two separate computers on the same local network, and i get the error code 10061, which is a full connect rejection. i do have a router, however i did add the port which i have been using for this program (6980), for TCP and it still fails to work...

MikeAThon
February 21st, 2008, 08:26 PM
The router is probably not involved, since both machines are on the same local network.

Are the machines ping'able from each other?

Check for the presence of firewalls on both/either of the client and server machines. As a first cut in debugging yur app, disable any firewalls that you find. Naturally, this can not be a final solution, but you need to start somewhere.

If the machines are ping'able, and if there are no firewalls, then re-post something closer to your actual code. Your code above shows a bunch of cout<< calls ( which are good). Please add a few more, and post the output, so that we can see which ip:port the client is connecting to, where the server is listening to, and the precise sequence of the code and where it fails.

Mike

tophat
February 22nd, 2008, 10:22 AM
thanks again for all of your help. the machines are pingable, and I have disabled firewall, and am getting these errors:


Enter user's IP Address: XX.XX.XX.XX
Enter port # to connect to: 6980
Connected to XX.XX.XX.XX:6980
Socket initialized
Connect failed, error: 10061
Press any key to continue...

MikeAThon
February 22nd, 2008, 01:05 PM
Please give us similar information about the server's output too.

Please also show us the IP's that are involved. This should not be a problem security-wise, since all the IP's at this point should be private, non-routable IP's, like 192.168.1.100.

Error 10061 is (as you know already) is WSAECONNREFUSED: No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host. Some typical reasons for this are that you went to the wrong host, or the server application you're trying to contact isn't executing. Check the destination address you are using. If you used a hostname, did it resolve to the correct address? Are you certain that the server is currently running and also currently listening on the intended port? It's for this reason that I am asking more questions about the server.

Mike

tophat
February 22nd, 2008, 02:39 PM
The server is listening on the port, because when you use 127.0.0.1, it connects only if you type the specified port (on client) that the server is listening to. The server is having no response to the connection from the client, it just keeps saying, "Waiting for client to connect..."

The IP addresses that are involved are my own, let's just say it's 10.90.68.1 or something (not anything like 127.0.0.1 or 192.168.1.100), and the server is listening on INADDR_ANY, so it should be listening on all of the available ip addresses.

Should this program even be capable of having the client connect to the server that is on an entirely different machine that isn't physically connected to the client machine?

MikeAThon
February 22nd, 2008, 03:00 PM
The server is listening on the port, because when you use 127.0.0.1, it connects only if you type the specified port (on client) that the server is listening to. The server is having no response to the connection from the client, it just keeps saying, "Waiting for client to connect..."
I have difficulty understanding this (maybe too many pronouns). Are you saying that when both the client and server are running on the same machine, the client can connect to the server on the specified port, whch proves to you that the server is listening on the correct port?

The IP addresses that are involved are my own, let's just say it's 10.90.68.1 or something (not anything like 127.0.0.1 or 192.168.1.100),
How are the IPs assigned? DHCP? Fixed? Are you certain that both machines are on the same local network? Exposing these IPs? Being ping'able will not show this, since pings will route through routers.

At this point in your testing, both machines must be on the same local network, and both must be exposing their respective IPs in the same local network. Your reluctance to give out IP numbers, and the format of the number you gave, make me suspect that your client is trying to connect to a routable, public IP address, or that your server is listening on the wrong IP address (maybe it has two NICs??).
and the server is listening on INADDR_ANY, so it should be listening on all of the available ip addresses.
No. INADDR_ANY will only listen on one IP address, and the "ANY" part lets the winsock stack select which one all by itself.

Run a "netstat -an" on the server, and post the results here. You should see a "LISTENING" indication next to port 6980, at an IP address that makes sense.

Should this program even be capable of having the client connect to the server that is on an entirely different machine that isn't physically connected to the client machine?
Certainly, as long as both machines are connected (wireless is OK) to the same network.

Mike

tophat
February 25th, 2008, 09:18 PM
The IP addresses I covered with X's were actually my IP, I just covered them with two X's even in points where there should have been 3 numbers. (Ex: if my ip was 12.34.678, i just put XX.XX.XX.) Anyways, I made sure they are pingable, and they are. The computers I am testing are on the same local network. I took your advice and ran netstat -an and found that my program was running on the desired port (I used 6980) and was listening on the IP 127.0.0.1, which was the IP bound using INADDR_ANY, and even sometimes it bound to 0.0.0.0, which I found to be kind of odd. So I believe the reason it won't work is because the server is binding to the localhost IP, and not the computer's IP address?

MikeAThon
February 26th, 2008, 11:03 AM
... So I believe the reason it won't work is because the server is binding to the localhost IP, and not the computer's IP address?
No, if netstat -an shows that your server is LISTENING at 0.0.0.0, then you should be OK.

Please review this thread and post the other information requested. I still don't understand your reluctance to show actual IPs. They should be private LAN IP's which are not routable, so there would never be a security issue. If they are actually public, routable IPs, then that's your problem, since the client can't find the server on the local LAN.

Again, being ping'able is good, but it doesn't guarantee that both machines are on the same LAN.

Does your server have two NICs?

tophat
March 1st, 2008, 12:10 PM
I believe that my IP's are private IP addresses. My server does not have two NICs. Both computers on the Local Network share the same IP address. Even if I have both the client and server program running on the same machine, it still doesn't work. Here is the exact output on both the server and client when I use my IP address (both client and server on the same machine):

Client:

Welcome

Commands:

c - Connect to computer
l - List commands
e - Exit Program

Command: c
Enter user's IP Address: 68.60.14X.XX
Enter port # to connect to: 6980
Connected to 68.60.14X.XX:6980
Socket initialized
Connect failed, error: 10060
Command:


10060 is a timeout error

Here is the server output:


Socket intialized...
Socket unbound...
Bind works...
Listen works...
Waiting for client...
Last error... (0)



And it just stays at that. When I try doing it with two separate computers on the same network sharing the same IP address, I get a 10061 error, connection forcefully rejected.

once again, I am trying to get this to work very much like a webserver where anyone can connect from a computer NOT on the local network and access information.

MikeAThon
March 1st, 2008, 03:50 PM
... Both computers on the Local Network share the same IP address.
This should not be possible and should be avoided even if it is possible. Each machine must have a unique IP address.
... Even if I have both the client and server program running on the same machine, it still doesn't work.
This is very different from your first post, where you told us that "they work flawlessly together by binding the client to 127.0.0.1, or the localhost".

I think you have probably changed your code considerably since you made your first post. For example, the code in your first post could not have produced the output you are showing now. Please zip up your project and post it here.

Finally, the IP address that you show (which I am masking as 68.60.1xx.yy, so you can edit your post and preserve your privacy) is not a private IP address, it's public. You're a Comcast customer, correct? I wouldn't have been able to determine that if you gave a private IP address, but with a public IP adddress it's easy.

At this stage of testing, you must use the private IP addresses that are local inside your LAN. At a command prompt for each machine, type "ipconfig". The IP address shown there is the address you should be trying to connect to. It should be something like 192.168.1.100. Post the output of ipconfig here, if you are not sure. If you are not seeing something like 192.168.1.100, then please tell us about your network configuration, i.e., the router/switch you are using, the modem/box with which you connect to the Internet, and how the Internet connection is shared with all others on the LAN.

In addition, please re-run your ping tests with these private IP addresses, to make certain that each machine is ping'able from the other.

Mike

tophat
March 2nd, 2008, 12:16 PM
Mike, thanks again for all of your help!

The program still works by using 127.0.0.1 within the local network, what I meant in my last post was that by using my public address it didn't work within the local network, which I see now is something that couldn't be done anyways.

I ran ipconfig on the server machine, and here is the output:



C:\Documents and Settings\Erik>ipconfig

Windows IP Configuration


Ethernet adapter Local Area Connection:

Connection-specific DNS Suffix . : hsd1.mi.comcast.net.
IP Address. . . . . . . . . . . . : 192.168.1.101
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1

C:\Documents and Settings\Erik>



Here is the ipconfig output for the client machine:



C:\Documents and Settings\Erik>ipconfig

Windows IP Configuration


Ethernet adapter Local Area Connection:

Connection-specific DNS Suffix . : hsd1.mi.comcast.net.
IP Address. . . . . . . . . . . . : 192.168.1.103
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1

C:\Documents and Settings\Erik>


i connected to the server successfully (192.168.1.101) and received the server response :).

Now how can I get this program to use public IP's so someone that's not on the network can connect to the server with the client program?

MikeAThon
March 2nd, 2008, 12:34 PM
Good. Phase one is completed: you are able to connect internally of the LAN.

And from the looks of your ipconfig output, your gateway is probably a router (Linksys, D-Link etc) that all machines on the LAN connect to, and which has a "special" connector for connecting a modem/cable box that gives shared access for all LAN machines to the Internet. Correct?

If so, then the important thing to understand is that your public (Comcast) IP is the IP address of the modem, not of any of the machines in your LAN.

Your modem is smart enough to send incoming connection requests to the router. (Since the modem is connected to only one device, it doesn't take much brains to do so.) The router, therefore, must be told what it should do with incoming connections.

That's where port-forwarding comes in. It's the exact same issues that Spasm mentioned many days ago, in his first post.

You must configure your router to forward incoming connection requests for the port your server is listening on, to the LAN address of the machine where the server is located. For your system, you must configure the router to forward incoming requests for port 6980 over to the machine located at 192.168.1.101

Your router probably has a convenient HTTP interface, for entering these settings, which you can find at http://192.168.1.1/ . If you do not understand how to effect these settings, then go to www.portforward.com , find the model of your router, and then follow the directions there.

Once the port forwarding is set, then remote users on the Internet can connect to your machine using the public IP address of your modem/router. They will need to enter the dotted numerical IP address.

Mike