Sign in to follow this  
jchmack

basic winsock help

Recommended Posts

i would have posted this in the networking section but it seems too simple... im trying to learn the basics of networking to add mulityplayer to my game. i can get my client program to send data to my server program through the loop ip 127.0.0.1 on the same computer. sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr( "127.0.0.1" ); service.sin_port = htons( 27015 ); i learned the basic code off MSDN but when i try to run the server program on my brothers computer which is over our LAN and i try to run the client program on my computer it is unable to connect. I've tried to change the 127.0.0.1 to 192.168.1.1 which is ip given to us by our router. And i have tried to change it to one given to me by ipchicken.com. how can i send data between client/server on different computers is there a way i can have my programs detect their own IP adresses? edit: how do i post my code in those boxes that display like a compiler? Thanks in advance =). [Edited by - jchmack on November 3, 2005 8:26:51 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by jchmack
i would have posted this in the networking section but it seems too simple...

im trying to learn the basics of networking to add mulityplayer to my game.

i can get my client program to send data to my server program through the loop ip
127.0.0.1 on the same computer.

sockaddr_in service;

service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
service.sin_port = htons( 27015 );

i learned the basic code off MSDN

but when i try to run the server program on my brothers computer which is over our LAN and i tru to run the client program on my computer it is unable to connect. I've tried to change the 127.0.0.1 to 192.168.1.1 which is ip given to us by our router. And i have tried to change it to one given to me by ipchicken.com.


Ip given to us?
Your computer and your brothers computer should have seperate IP addresses, it sounds like you are refuring to the IP address of your router itself.

Quote:

how can i send data between client/server on different computers
is there a way i can have my programs detect their own IP adresses?


check out the gethostname function on google or MSDN. You can also open up a command prompt and type the word ipconfig to do it manualy to verify that your program is running correctly

Quote:

edit: how do i post my code in those boxes that display like a compiler?


use 'source' tags: [s.ource] my code here [/s.ource] (without the periods)

Hope that helped

Share this post


Link to post
Share on other sites
Quote:
Original post by jchmack
i would have posted this in the networking section but it seems too simple...

im trying to learn the basics of networking to add mulityplayer to my game.

i can get my client program to send data to my server program through the loop ip
127.0.0.1 on the same computer.

sockaddr_in service;

service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
service.sin_port = htons( 27015 );

i learned the basic code off MSDN

but when i try to run the server program on my brothers computer which is over our LAN and i tru to run the client program on my computer it is unable to connect. I've tried to change the 127.0.0.1 to 192.168.1.1 which is ip given to us by our router. And i have tried to change it to one given to me by ipchicken.com.

how can i send data between client/server on different computers
is there a way i can have my programs detect their own IP adresses?

edit: how do i post my code in those boxes that display like a compiler?

Thanks in advance =).



You're right in that you need to use the IP given to you by the router, but in my experiance 192.168.1.1 is the address one gives a web browser to goto the configuration. It's not the address you need use to connect to another machine on that router. If you're running Windows XP click start, run then type cmd and hit enter or ok. Then in the resulting window type ipconfig and hit enter. Use address labeled IP address. Obviously you do this on the machine you want the ip address of.

Share this post


Link to post
Share on other sites
what i meant was:
192.168.1.100
is the ip that shows up for my brothers computer in the clients table

so i go on my brothers comp find his ip with ipcofig.
then change
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );

to
service.sin_addr.s_addr = inet_addr( his ip );

in the client program?

edit:
i ran ipconfig on my brothers computer and it said his ip was 192.168.1.100 which i have tried. I also ran it on mine and it gave 192.168.1.101. Both just like my router client table.

Share this post


Link to post
Share on other sites
this is what i used to gethost name

char a2[100];
gethostname(a2,100);
cout <<"your hostname is: " << a2 << endl;

it outputs the-behemoth which is the name of my computer on our network.
am i supposed to put this into my:
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );

anyways here is the source:

server:



#include <stdio.h>
#include "winsock2.h"

#include <string>
#include <iostream>

using namespace std;

void main() {

// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");

// Create a socket.
SOCKET m_socket;
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( m_socket == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return;
}

// Bind the socket.
sockaddr_in service;

service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
service.sin_port = htons( 27015 );

if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
printf( "bind() failed.\n" );
closesocket(m_socket);
return;
}

// Listen on the socket.
if ( listen( m_socket, 1 ) == SOCKET_ERROR )
printf( "Error listening on socket.\n");

// Accept connections.
SOCKET AcceptSocket;

char *a1;
a1 = inet_ntoa(service.sin_addr);
cout <<"your ip is: " << a1 << endl;

char a2[100];
gethostname(a2,100);
cout <<"your hostname is: " << a2 << endl;

printf( "Waiting for a client to connect...\n" );
while (1) {
AcceptSocket = SOCKET_ERROR;
while ( AcceptSocket == SOCKET_ERROR ) {
AcceptSocket = accept( m_socket, NULL, NULL );
}
printf( "Client Connected.\n");
m_socket = AcceptSocket;
break;
}

// Send and receive data.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[32] = "Server: Sending Data.";
char recvbuf[32] = "";

bytesRecv = recv( m_socket, recvbuf, 32, 0 );
printf( "Bytes Recv: %ld\n", bytesRecv );

bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );


//string input="null";
//char input[1];//='$';
int a =0;

while(a==0)
{
recv( m_socket, recvbuf, 32, 0 );
for(int b=0;b<strlen(recvbuf);b++)
cout << recvbuf[b];

cout << endl;

/*recv( m_socket, input, 1, 0 );
cout << input[0];

cout << endl;*/

}

return;
}






client:

#include <stdio.h>
#include "winsock2.h"

#include <string>
#include <iostream>

using namespace std;

void main() {

// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");

// Create a socket.
SOCKET m_socket;
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( m_socket == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return;
}

// Connect to a server.
sockaddr_in clientService;

clientService.sin_family = AF_INET;

clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 27015 );

//clientService.sin_addr.s_addr = inet_addr( "192.196.1.100" );
//clientService.sin_addr.s_addr = inet_addr( "68.92.103.49" );
//clientService.sin_port = htons( 1640 );

if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return;
}

// Send and receive data.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[32] = "Client: Sending data.";
char recvbuf[32] = "";

bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

while( bytesRecv == SOCKET_ERROR ) {
bytesRecv = recv( m_socket, recvbuf, 32, 0 );
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
printf( "Connection Closed.\n");
break;
}
if (bytesRecv < 0)
return;
printf( "Bytes Recv: %ld\n", bytesRecv );
}

int a=0;
string out;
/*cout << "enter something to clear cin" << endl;
getline(cin,out);
getline(cin,out);*/


while(a==0)
{
cout << "enter an input to send:" << endl;
cin >> out;
cout << "sending string: " << out <<endl;
for(int b=0;b<strlen(sendbuf);b++)
{
if(b<out.length())
{
sendbuf[b]=out[b];
}
else
{
sendbuf[b]=' ';
}

}
send( m_socket, sendbuf, strlen(sendbuf), 0 );
}

return;
}





what should i be binding my sockets to?

i am using microsoft visual c++ 6.0
and i have linked the winsock 2 library correctly (i hope)
post if u need any more info

[Edited by - jchmack on November 3, 2005 9:43:46 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by jchmack
this is what i used to gethost name

char a2[100];
gethostname(a2,100);
cout <<"your hostname is: " << a2 << endl;

it outputs the-behemoth which is the name of my computer on our network.
am i supposed to put this into my:
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );


Use the output of gethostname() in a call to gethostbyname().
gethostbyname() returns a hostent structure, and one of the members is the address.

I think the function is technically depreciated, but the replacement is getaddrinfo() which will probably only confuse a beginner.


Quote:

anyways here is the source:

server:
*** Source Snippet Removed ***


client:
*** Source Snippet Removed ***

what should i be binding my sockets to?

i am using microsoft visual c++ 6.0
and i have linked the winsock 2 library correctly (i hope)
post if u need any more info


a quick run through - I see that you havn't set your sin_zero member of the sockaddr_in to zero. You must do that, but I'm not sure if that is your problem. Try changing that and let me know if your problem is solved.

Share this post


Link to post
Share on other sites
Each computer on a network has one IP address (or more). A router typically has two IP addresses: one for each network it routes. In this case, it routes your private network to the greater internet, and thus has two addresses -- you probably get the external network address of your router when you to go an external site to see what your IP is; that's because your router probably does NAT (rather than assigning an external address per internal host). For more information on that, see the FAQ in the networking forum.

Because each network interface needs an IP address, the network card is one interface, and the loopback device is another interface. The loopback device is given the address 127.0.0.1 on all machines, so whenever you're using that address, your networking will only work within that single machine.

There are two ways of using IP addresses: for binding (on the listening/"server" side) and for connecting (on the connecting/"client" side).

When you bind() a socket, it ties that socket to a specific network device, or set of network devices. The network devices are identified by IP address. If you bind() to the address 127.0.0.1, that means that only someone connecting to 127.0.0.1 on the local machine will connect to that socket. Typically, you want to bind to the address INADDR_ANY, which resolves to 0.0.0.0, this is an alias for "any and all IP interfaces on this machine".

When you connect() a socket, you're establishing a connection to some remote socket. If you pass in the address 127.0.0.1, it means that you're connecting only to the local machine. Instead, you need to put in the IP address of the remote machine.

To find the IP address (or addresses) of interfaces on a Windows machine, type "ipconfig" in the command line window. To do the same thing on UNIX, type "ifconfig" (on some Unixen, you need to be root to do this).

So, when you bind(), you should bind to INADDR_ANY, and when you connect(), you should connect to whatever address is given to you by running ipconfig on the machine you want to connect TO (i e, the machine that did the bind()).

If you have more questions related to this topic, I invite you to stop by the networking forum.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nuget5555
Use the output of gethostname() in a call to gethostbyname().
gethostbyname() returns a hostent structure, and one of the members is the address.

I think the function is technically depreciated, but the replacement is getaddrinfo() which will probably only confuse a beginner.


i tried all of these on my client:
char a2[100];
gethostname(a2,100);
gethostbyname(a2);

clientService.sin_addr.s_addr = inet_addr( "192.196.1.100" )//the ip given in ipconfig

gethostbyname("hpcomputer");//the name of my brothers (sever) computer on our network

and none of them worked

Quote:
Original post by Nuget5555
a quick run through - I see that you havn't set your sin_zero member of the sockaddr_in to zero. You must do that, but I'm not sure if that is your problem. Try changing that and let me know if your problem is solved.


clientService.sin_zero=0;
gives me errors
how do i set to 0;

Quote:
Original post by Cybergolem
Did you check that you get through the firewall of your brohers computer?
try to disable it and see if it helps.


i dont think we have a firewall enabled but how can i check just to make sure

Quote:
Original post by hplus0603
When you bind() a socket, it ties that socket to a specific network device, or set of network devices. The network devices are identified by IP address. If you bind() to the address 127.0.0.1, that means that only someone connecting to 127.0.0.1 on the local machine will connect to that socket. Typically, you want to bind to the address INADDR_ANY, which resolves to 0.0.0.0, this is an alias for "any and all IP interfaces on this machine".


i tried this on my server:

service.sin_addr.s_addr = inet_addr( "0.0.0.0" );

which works when i run the client on my computer using the loop back ip

when i use:
clientService.sin_addr.s_addr = inet_addr( "192.196.1.100" ); //my brother
on my client it pauses a while (like its attempting to connect) before saying
"connection failed"

ive also tried running both the client and sever on my computer using:
clientService.sin_addr.s_addr = inet_addr( "192.196.1.101" ); /my ip from ipconfig
on my client (anything but the loopback)

the only way i can get this to work is by using the loopback ip.

i think id probably learn better from example. Is there any source out there that uses winsock that sends strings between a client/server(not using 127.0.0.1) either over a LAN or a internet connection. (kinda like mine does but it works lol)

[Edited by - jchmack on November 4, 2005 2:25:42 AM]

Share this post


Link to post
Share on other sites
Check the firewall settings on hes PC if you get an error connecting, as cybergolem said.
If it works using 127.0.0.1 that would be my guess

Windows XP has options to open a speciffic port in the firewall

Share this post


Link to post
Share on other sites

I have norwegian text in my windows menus, but I think i remeber the english counterparts more or less...

1 Open Control panel
2 Go to network connections (or something like that)
3 Right click the active network card on the list choose the bottom
option (Settings or something)
4 Go to the "Advanced" tab sheet

If you activate the firewall, you will get a Settings button at the bottom
where you can get more detailed control.
However if the firewall if not active this shouldnt be the problem.

Aslo if your client/server works when you run them on your own PC, and using 127.0.0.1, the program works. (I think I said that already ^^)

EDIT:
Im testing it and there is something fishy here for sure.
Ill post if i find the problem

[Edited by - pulpfist on November 4, 2005 10:11:21 PM]

Share this post


Link to post
Share on other sites
Ok I got it!

Its the accept call in the server

change:

// Bind the socket.
sockaddr_in service;

to:

// Bind the socket.
sockaddr_in service, client;


and change:


printf( "Waiting for a client to connect...\n" );
while (1) {
AcceptSocket = SOCKET_ERROR;
while ( AcceptSocket == SOCKET_ERROR ) {
AcceptSocket = accept( m_socket, NULL, NULL );
}
printf( "Client Connected.\n");
m_socket = AcceptSocket;
break;
}

to:

printf( "Waiting for a client to connect...\n" );
AcceptSocket = SOCKET_ERROR;
int sin_size = sizeof(struct sockaddr_in);
while ( AcceptSocket == SOCKET_ERROR )
AcceptSocket = accept( m_socket, (struct sockaddr *)&client, &sin_size);
printf( "Client Connected.\n");
m_socket = AcceptSocket;


accept is a blocking call so no need to put it in a loop (until you make it non-blocking ofcourse)
By doing it this way your server also have detailed info about the connected client in the "client" struct :p

The original code you posted works fine apart from that, even though you
should prolly use INADDR_ANY as stated by hplus

...
service.sin_addr.s_addr = INADDR_ANY;
...


And consider terminating the data recieved (not sure recv does that for you but better be sure)

...
int num_bytes = recv( m_socket, recvbuf, 32, 0 );
recvbuf[num_bytes] = '\0';
...



[Edited by - pulpfist on November 5, 2005 12:26:39 AM]

Share this post


Link to post
Share on other sites
ok i got it =)
i did what pulp said and opened a port on my router (in port forwarding).

service.sin_port = htons( 27015 );
requires port 27015 to be forwarded to my bros computer.

yay ty guys for all the help

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this