My server is up and running (connecting through telnet worked so I know its functional) but my client cannot seem to establish a connection. I have a feeling it has something to do with the way I'm filling out the sockaddr_in serverAddr struct.
Can anyone please help? Thank you.
int clientSocket;
char hostname[256];
struct sockaddr_in serverAddr;
struct hostent *host;
socklen_t theirAddrSize;
gethostname(hostname, sizeof(hostname));
host = gethostbyname(hostname);
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr( host->h_name );
serverAddr.sin_port = htons( 30000 );
if ( clientSocket = socket( AF_INET, SOCK_STREAM , 0 ) == -1) {
cerr << "socket failed ; exiting..." << endl;
exit(1);
}
if ( connect( clientSocket , (struct sockaddr *) &serverAddr , sizeof(serverAddr) ) == -1 ) {
cerr << "connect failed ; exiting..." << endl;
exit(1);
}
connect always returns -1.
Instead of inet_addr(host->h_name), use host->h_addr_list[0].
Does this work?
memcpy(&serverAddr.sin_addr,
host->h_addr,
sizeof(serverAddr.sin_addr));
As far as I can see there's nothing wrong with the code you've posted here. It's pretty much identical with socket client code I've been writing for years. So the problem either lies elsewhere in the code, or it's in the data.
Ah - you've edited the code... and added some comments. OK, the return value from inet_addr is -1 (4294967295 == 0xFFFFFFFF == -1 == INADDR_NONE), so it doesn't seem to like what you're passing it.
You need to run the code through a debugger, concentrating on the calls to gethostname and gethostbyname. I'm assuming this is test code, since you're connecting to the same machine you're running on.
I did require the memcpy but alot of this headache stemmed from a very mindless syntax error:
if ( clientSocket = socket( AF_INET, SOCK_STREAM , 0 ) == -1)
I had to wrap the assignment in parenthesis before comparing it to -1.
if (( clientSocket = socket( AF_INET, SOCK_STREAM , 0 )) == -1)
Gah, you live you learn :)
Related
Here is a sample socket programming snippet from the client side. My question revolves around the type-casting that casted sockaddr_in into sockaddr. My question is that why is that casting necessary there, what is going on there exactly?
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int main ( int argument, char const *argv[] )
{
int obj_socket = 0, reader;
struct sockaddr_in serv_addr;
char *message = "A message from Client !";
char buffer[1024] = {0};
if (( obj_socket = socket (AF_INET, SOCK_STREAM, 0 )) < 0)
{
printf ( "Socket creation error !" );
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton ( AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf ( "\nInvalid address ! This IP Address is not supported !\n" );
return -1;
}
if ( connect( obj_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr )) < 0) // <--- QUESTION ABOUT THIS LINE
{
Printf ( "Connection Failed : Can't establish a connection over this socket !" );
return -1;
}
send ( obj_socket , message , strlen(message) , 0 );
printf ( "\nClient : Message has been sent !\n" );
reader = read ( obj_socket, buffer, 1024 );
printf ( "%s\n",buffer );
return 0;
}
I've been reading the documentation and going throughout the header files to understand the structures however there is one last thing that I couldn't get.
The <sys/socket.h> header defines the sockaddr structure that includes
at least the following members:
sa_family_t sa_family address family
char sa_data[] socket address (variable-length data)
The <netinet/in.h> header shall define the sockaddr_in structure,
which shall include at least the following members:
sa_family_t sin_family AF_INET.
in_port_t sin_port Port number.
struct in_addr sin_addr IP address.
My question is, at this line of the code:
if ( connect( obj_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr )) < 0)
What is the purpose of this casting here which casted sockaddr_in to sockaddr. I understand that it is mandatory to cast here, but I would like to know why is it so? Thank you
What is the purpose of this casting here which casted sockaddr_in to sockaddr.
sockaddr_in is not casted to sockaddr. sockaddr_in* is casted to sockaddr*.
That cast is done because the function connect which is being called doesn't accept a sockaddr_in* parameter, but a sockaddr*.
P.S. I recommend to not manually create a sockaddr_in, but instead to use getaddrinfo to create it.
P.P.S char *message = "A message from Client !"; is ill-formed in C++. The code that you've posted seems to be C rather than C++.
new to multicast networking, I need to receive UDP packets from a multicast channel through one of the NICs on my windows box, followed Microsoft docs and some blog entry, but still having issues.
I create a socket via
ls = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
call.
Then setsockopt to SO_REUSEADDR
unsigned int reuse = 1;
if( setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0 )
{
LOG4CXX_ERROR(logger, "Reusing ADDR failed. Err: " << WSAGetLastError());
}
If socket is good
int result = bind(ls, reinterpret_cast<SOCKADDR*>(&server), sizeof(server));
where
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(myport);
If bind succedes
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if( setsockopt(ls, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0 )
{
LOG4CXX_ERROR(logger, "setsockopt multicast group add membership failed. Err: " << WSAGetLastError());
}
The box on which I need to receive packets has four NICs, network administrators told me that I have to use the third one, let's say that it has a.b.c.d IPv4 address
They told me also that mcast IP is e.f.g.h
If I run windump.exe -i 3 on my windows box I see something like this
... 12:53:58.454987 IP i.k.l.m.xxxxx > e.f.g.h.myport: UDP, length 58
...
After initializing my UDP socket I call recvfrom
sz = recvfrom(ls, buffer, DATA_BLOCK_SIZE, 0, reinterpret_cast<SOCKADDR*>(&client), &size);
where sz is an int, ls is my socket, buffer is a "suitable buffer", DATA_BLOCK_SIZE is buffer size, client is a SOCKADDR pointer to receive info from the sender, and size is the received message size.
My code stucks in the recvfrom call never receiving anything.
I'm clearly making a mistake somewhere but not understanding where and worse why.
If someone can explain me what's happening it will be very appreciated.
SOLVED ...
I changed these lines only
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
to
struct ip_mreq mreq;
inet_pton(AF_INET, "e.f.g.h", &(mreq.imr_multiaddr));
inet_pton(AF_INET, "a.b.c.d", &(mreq.imr_interface));
As I have guessed I was not correctly indicating in my struct ip_mreq which was the network interface to use for multicast messages.
It was my fault. Sorry for the noise.
I am having a strange error that I can't find anywhere online. I am attempting to open a socket and bind it so I can send a UDP packet. However, the when I try to check if the bind succeeds, it won't compile. From what I have read, bind() is supposed to return an int, but for some reason it is not doing it in my program.
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
// handle errors
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(0);
if (bind(sock, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) {
cout << "Binding error\n";
return false;
}
return true;
My only guess is that bind() is getting overloaded somehow (Maybe another library that I have included)
Could be conflict with std::bind in C++. Try prepending global namespace:
::bind(sock, (struct sockaddr*)&local, sizeof(local))
The better solution is stop using namespace std; once and for all. It does you much more harm than good (taking into account, it does you no good whatsoever).
at the first , my partner supply me an IP , and I communicate with this IP using socket , below is my code
SOCKADDR_IN target;
target.sin_family = AF_INET;
target.sin_port = htons (8081);
target.sin_addr.s_addr = inet_addr ("192.168.0.102");
mThreadSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (mThreadSocket == INVALID_SOCKET)
{
return ;
}
//Try connecting...
if (connect(mThreadSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
LogTrace( TBCAF_TRACE_LEVEL_ERROR, FWARNING"Winsock started fail." );
return ; //Couldn't connect
}
LogTrace(TBCAF_TRACE_LEVEL_4, FYELLOW"CCloudInterface: connected.");
u_long iMode=1;
ioctlsocket(mThreadSocket,FIONBIO,&iMode);
while(true)
{
if (!process_receive())
continue;
if(!process_send())
continue;
// above two function both use the socket "mThreadSocket"
}
above code works fine , but recently my partner supply me two IP , and say when one is down , I can switch to another one to avoid communication loss , but wat should I do ?
should I open two connected socket at the beginning , and use one socket first,
switch to another one when the first is down ?
or should I only keep one socket open , then make a function for example call ReConnect() , and in this functon change socket 's IP ? but how to do it
any help is appreciate , thank u .
I am trying to implement UpNP in C++, I found a few sources on google but none worked. I found this one working (http://www.codeproject.com/KB/IP/upnplib.aspx) but it's for .NET, so I decided to sniff the network to see what the code was doing and then do the same with sockets.
Here are the results (full size: http://i.stack.imgur.com/eLoHK.jpg):
That shows me that the packet doesn't look bad, everything seems to be the same, everything but the source address of my code, which I don't know how to control (both my code and finder.net.exe are being tested on the same computer connected to the same network).
Here's my code:
#define upnp_broadcast_ip "239.255.255.250"
#define upnp_broadcast_port 1900
#define upnp_search_request "M-SEARCH * HTTP/1.1\r\n" \
"Host:239.255.255.250:1900\r\n" \
"ST:upnp:rootdevice\r\n" \
"Man:\"ssdp:discover\"\r\n" \
"MX:3\r\n" \
"\r\n"
WSAStartup(MAKEWORD(2, 2), &WsaData);
BOOL discover( )
{
SOCKET ConnectSocket;
struct sockaddr_in Addr;
char Buffer[1450];
int t = 0,
iResult = 0,
TrueLen = sizeof(bool);
bool True = true;
ulong One = 1;
// Open datagram socket
ConnectSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
// Clear out struct
memset( &Addr, 0, sizeof(Addr) );
// Specify the address family, IP address, and port
Addr.sin_family = AF_INET;
Addr.sin_port = htons( upnp_broadcast_port );
Addr.sin_addr.s_addr = inet_addr( upnp_broadcast_ip );
iResult = setsockopt( ConnectSocket, SOL_SOCKET, SO_BROADCAST, (char*)&True, TrueLen ); // Not sure what is this for
// Transmit data
int sent = sendto( ConnectSocket, upnp_search_request, strlen(upnp_search_request), 0, (struct sockaddr*)&Addr, sizeof(Addr) );
// Try to receive data 10 times
for( t = 0; t < 10; t++ )
{
ioctlsocket( ConnectSocket, FIONBIO, &One );
// Clear out buffer
memset( &Buffer, 0, sizeof(Buffer) );
int length = sizeof(Addr);
// Receive data
iResult = recvfrom( ConnectSocket, Buffer, (sizeof(Buffer) - 1), 0, (struct sockaddr*)&Addr, &length );
if( iResult == SOCKET_ERROR)
{
Sleep( 1000 );
continue;
} else {
// Do stuff with received data
}
}
closesocket( ConnectSocket );
return FALSE;
}
I removed all the WSAGetLastError() error checking to make the code easier to read, everything goes fine until recvfrom, that always returns -1 and strerror(WSAGetLastError()) prints "Unknown error".
I hope someone could guide me in the right direction, I've been the last two days trying to make this work.
Why broadcast? UPnP uses multicast, so as far as I remember (Unix) you should use setsockopt() to request that the kernel join a multicast group. I am not sure about Windows, it could be the same call.
Something like:
struct ip_mreq mreq;
....
mreq.imr_multiaddr.s_addr=inet_addr(GROUP_IP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))
EDIT:
As hasturkun pointed out, my initial answer was wrong. Also, slemdx correctly diagnosed the problem: the uPnP request is going out from the wrong interface. The problem is, I am not sure how you can determine the right interface. One possibility is to use the interface containing the default gateway on the routing table, but I don't think that would be the right choice. There may be uPnP devices hooked to other interfaces.
One option is to send the initial search packet on all available interfaces. Maybe the answers to this question can help. There is also another link on the last answer that you should check out.