bind: Socket operation on non-socket - c++

I writing a server and a client and keep getting 'bind: Socket operation on non-socket'.
I've researched the heck out of this, have other code that runs in another application and have exhausted 8 hours trying to find this bug.
The code is:
void TCPSocket::buildTCPSocket(int port)
{
initializeSocket1();
getSocket();
bindSocket();
listenToSocket();
acceptSocket();
// now you can send() and recv() with the
// connected client via socket connectedTCPSocket
}
void TCPSocket::getSocket()
{
// Get an internet domain socket AF_INET
if(socket1 = socket(AF_INET, SOCK_STREAM,0) == -1)
{
perror("socket");
exit(1);
}
}
void TCPSocket::bindSocket()
{
// Bind to a port on the host
int myAddressSize = sizeof(myAddress);
int bindReturnValue = bind(socket1, (struct sockaddr *) &myAddress, AddressSize);
if (bindReturnValue == -1)
{
perror("bind"); // <== Error message generated here
exit(1);
}
printf("Socket for TCP bound to port %d\n", port);
}
Also, prior to this, I memset the memory block with this function.
void TCPSocket::initializeSocket1()
{
// Fill tcpSocket struct with 0's
memset(&myAddress, '\0', sizeof(myAddress));
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = INADDR_ANY;
// Conver PORT to big-endian if necessary
myAddress.sin_port = htons(this->port);
}
Variables are declared in the header file of the class.
public:
struct sockaddr_in myAddress, clientAddress;
void buildTCPSocket(int newPort);
private:
int port;
int socket1, socket2;
socklen_t clientAddressLength;
-- Edit the code should be a little more clear now. socket1 is initialized in getSocket().
I've seen where a bunch of guys have missed the parens in the if but I think I eliminated that error by declaring myAddressSize and bindReturnValue.
Any input is appreciated.
Thank you,
Ted S
Ok, problem solved. Of course the problem is never where you are looking are you would have found it. Here is the corrected code. The problem was in a missing set of parens in the call to socket().
void TCPSocket::getSocket()
{
// Get an internet domain socket AF_INET
if((socket1 = socket(AF_INET, SOCK_STREAM,0)) == -1)
{
perror("socket");
exit(1);
}
}
Thanks again!

I can almost guarantee you that you're getting that error because you never initialized socket1.
Typically you have to do something like this:
int socket1 = socket(AF_INET, SOCK_STREAM, 0);
bind(socket1, ...);
I don't see any code anywhere in there for setting up socket1. This is what the error message is telling you, after all. socket1 isn't a socket, so it's failing.
Edit: As a follow up, this is one of the reasons why I try to avoid using the syntax
if ((foo = bar()) == ERROR)
{
// handle me
}
And instead stick with:
void TCPSocket::getSocket()
{
// Get an internet domain socket AF_INET
socket1 = socket(AF_INET, SOCK_STREAM, 0);
if (socket == -1)
{
perror("socket");
exit(1);
}
}

Related

Directed UDP to IP address that doesn't exist

I am experiencing slowdowns when attempting to send a UDP message to an IP address that is non-existent. We read a list of IP/ports out of a configuration file and expect that those combinations will exist. In some situations, the remote machine may not be online yet and the IP will not exist on the network. In this case, i would prefer that we do not attempt to send the data.
I'm looking for suggestions on a good way to determine that the IP doesn't exist in order to skip sending the data. I do not want to completely remove it from the list because there is the chance that the machine may come online and i'd like to continue sending data.
Relevant code:
int SendData(const char *data, int size, bool openIfClosed)
{
std::lock_guard<std::mutex> lock(sendMutex);
//if the socket was not already opened, close it after i do my send
bool closeAfterSend = mySocket == INVALID_SOCKET ? true : false;
if (!OpenSocket(openIfClosed))
return 0;
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(remotePort);
address.sin_addr.s_addr = remoteIPAddress.GetIPAddressAsULong();
//check if remote address exists prior to send?
int bytesSent = sendto(mySocket, data,
size, 0, (struct sockaddr *)&address, sizeof(address));
if (bytesSent == size)
numMsgsOut++;
else
{
//fail
}
if (closeAfterSend && openIfClosed)
{
closesocket(mySocket);
mySocket = INVALID_SOCKET;
}
return bytesSent;
}

Why isn't AF_INET working with SOCK_STREAM?

I'm just starting out on gaining a better understanding of socket programming, and I'm trying to build a simple program that can send and receive messages. I've run into an issue with binding a socket to an address to use it. Here is what I have-
#include "stdafx.h"
using namespace std;
int main()
{
bool devbuild = true;
WSADATA mainSdata;
SOCKET sock = INVALID_SOCKET;
sockaddr tobind;
tobind.sa_family = AF_INET;
char stringaddr[] = "192.168.1.1";
inet_pton(AF_INET,stringaddr,&tobind);
//initiating Windows Socket API (WSA)
if (WSAStartup(2.2, &mainSdata) == 0)
{
if (devbuild == true)
{
printf("WSA successfully started...\n");
}
}
else
{
printf("WSA failed to set up, press [ENTER] to exit...\n");
pause();
return 1;
}
//instantiating the socket
sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, NULL);
if (sock != INVALID_SOCKET)
{
if (devbuild == true)
{
printf("Socket successfully created...\n");
}
}
else
{
printf("Socket failed to set up, press [ENTER] to exit...\n");
pause();
return 2;
}
//binding the socket
if (bind(sock, &tobind, sizeof(tobind)) == 0)
{
if (devbuild == true)
{
printf("Socket successfully bound...\n");
}
}
else
{
printf("Socket failed to bind, press [ENTER] to exit...\n");
printf("Last WSA error was: %d", WSAGetLastError());
pause();
return 3;
}
pause();
return 0;
}
I'm getting a return of 3, with WSA error code 10047
10047 - WSAEAFNOSUPPORT
Address family not supported by protocol family.
An address incompatible with the requested protocol was used. All sockets are created with an associated address family (that is, AF_INET for Internet Protocols) and a generic protocol type (that is, SOCK_STREAM). This error is returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, for example, in sendto.
This doesn't make sense, because I am only using SOCK_STREAM and AF_INET, which support one another.
I believe one problem (possibly not the only problem, but this is what jumps out at me) is in this line:
inet_pton(AF_INET,stringaddr,&tobind);
The problem is that you are passing &tobind as the final argument, and tobind is a sockaddr, but inet_pton() expects its third argument to point to a struct in_addr instead when using AF_INET (the fact that inet_pton() takes a void-pointer rather than a typed pointer for its third argument makes this kind of mistake really easy to make).
So what you should be doing instead is (note added error checking also):
if (inet_pton(AF_INET,stringaddr,&tobind.sin_addr) != 1)
printf("inet_pton() failed!\n");
Also, you need to make tobind be of type struct sockaddr_in rather than just a sockaddr, and also you need to zero out the struct before using it:
struct sockaddr_in tobind;
memset(&tobind, 0, sizeof(tobind)); // make sure the uninitialized fields are all zero
tobind.sa_family = AF_INET;
[...]

TCP Socket. Error no matching function call

The following is the error I am receiving as well as the small section of code from with it comes from. Could someone please explain what this error means. I have used this connect call in many other programs successfully and I don't know why it fails here. Thank you!
error: no matching function for call to 'Pds::MonReqServer::connect(int&, sockaddr*, long unsigned int)'
///SETUP TCP SOCKET///
int tcp_socket_info;
struct sockaddr_in tcp_server;
//create socket
tcp_socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket_info == -1) {
printf("Could not create socket");
}
//assign values
tcp_server.sin_addr.s_addr = inet_addr("192.168.0.100"); //address of sender
tcp_server.sin_family = AF_INET;
tcp_server.sin_port = htons( 1100 );
//connects
if (connect(tcp_socket_info, (struct sockaddr *)&tcp_server, sizeof(tcp_server)) < 0) {
perror("Connection error");
}
puts("Connected");
Judging by what you're doing, you didn't mean to use Pds... anything. If you really meant to use the standard connect() function, try prefixing it with ::

Win Socket UDP connection-less recvfrom() Error

I'm working on a legacy VC6 application, that uses winsocket to listen to a UDP port for incoming packets. However I am getting the following errors. If I use WSAGetLastError() I get WSAECONNRESET, which if I read the description, doesn't seem to make sense, because its saying that remote host forcibly closed the socket, But I want use UDP connection-less manor, so it shouldn't matter what the other machine is doing... we should just listen. If I check the errno and use sterror() I get the following message. "No such file or directory". (I think this it's enum is EIO, according to http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html)
I've had some success in narrowing down the issue, it appears if I take out a sendto() call, that calls back on the same port as the recvfrom(), the code seems to work ok. So something with that sendto() is putting in a bad state.
I'm looking for suggestions on why this socket is going bad, and either how to prevent or recover.
Edit
Here is the other weird part, if do the setup again for that socket (after a recvfrom() fails)... it all seems to work, even additional calls to sendto() don't seem trigger a recvfrom() fail, which in turn would call the setup again..
CODE
static VOID SetupSocketAddress( SOCKADDR_U &saRx, int nRTDPort )
{
memset(&saRx.saIPX, 0, sizeof(SOCKADDR_IPX));
saRx.saIPX.sa_family = AF_IPX; // IPX type address
memset(saRx.saIPX.sa_netnum,0x00,4); // we may have to get this number
memset(saRx.saIPX.sa_nodenum,0xff,6); // broadcast address
saRx.saIPX.sa_socket=(unsigned short)nRTDPort; // socket number
}
void CRealTimeData::SetupSocket( CRealTimeData * lpRTD, BOOL &bDone, SOCKADDR_U &saRx, int nRTDPort, SOCKADDR_U &saFrom, int &cbAddr,
DWORD &dwLocalAddress, int &nMaxIpIpxBuf, char * &pbyIpIpxRxBuf, int nFlags, BOOL bDo)
{
char szErrorCode[32];
int nReturn = 0;
if (lpRTD->m_eSourceType == V7_RTD_IPX)
{
// open IPX socket
// packet type = 4
lpRTD->m_Socket=socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX+4);
if (lpRTD->m_Socket == INVALID_SOCKET)
{
nReturn = AddSocketErrorToEventViewer( lpRTD);
bDone = TRUE;
}
// Socket must be bound prior to calling recvfrom()
// setup address
SetupSocketAddress(saRx, nRTDPort);
#ifdef _DEBUG_IPX
// test changing host number to network number
// we can't actually change though, because other programs use it this way
u_short nNetPort=0;
int nRet=WSAHtons(lpRTD->m_Socket, (unsigned short)nRTDPort, &nNetPort);
TRACE(_T("RTDIpxThread: Host Port=%04x Net Port=%04x RTD Input=%d \n"),nRTDPort, nNetPort, lpRTD->GetInputNumber());
#endif
// setup address for Sending Data on RTD
SetupSocketAddress( lpRTD->m_saRTD, nRTDPort );
// copy address - Why are we copying the address just over right later (in recvfrom() )? -NG
memcpy(&saFrom.saIPX, &lpRTD->m_saRTD.saIPX, sizeof(SOCKADDR_IPX));
cbAddr = sizeof(SOCKADDR_IPX);
}
else
{
// open IP socket
lpRTD->m_Socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); // ??? should this use IPPROTO_UDP???
if (lpRTD->m_Socket == INVALID_SOCKET)
{
nReturn = AddSocketErrorToEventViewer( lpRTD);
bDone = TRUE;
}
// Socket must be bound prior to calling recvfrom()
// setup address
memset(&saRx.saIP, 0, sizeof(SOCKADDR_IN));
saRx.saIP.sin_family = AF_INET; // IP type address
saRx.saIP.sin_port=htons((u_short)nRTDPort); // PORT number
saRx.saIP.sin_addr.s_addr=htonl(INADDR_ANY); // ADDRESS number
// setup for Sending Data on RTD port
memset(&lpRTD->m_saRTD.saIP, 0, sizeof(SOCKADDR_IN));
lpRTD->m_saRTD.saIP.sin_family = AF_INET; // IP type address
lpRTD->m_saRTD.saIP.sin_port=htons((u_short)nRTDPort); // PORT number
lpRTD->m_saRTD.saIP.sin_addr.s_addr=htonl(INADDR_BROADCAST); // ADDRESS number
// copy address - Why are we copying the address just over right later (in recvfrom() )? -NG
memcpy(&saFrom.saIP, &lpRTD->m_saRTD.saIP, sizeof(SOCKADDR_IN));
cbAddr = sizeof(SOCKADDR_IN);
char szHostName[MAX_PATH+1];
if (gethostname(szHostName, MAX_PATH)==0)
{
hostent *phe=gethostbyname(szHostName);
dwLocalAddress = *(DWORD*)&phe->h_addr_list[0];
}
} // end IP socket
if (!bDone)
{
// enable broadcasting
BOOL bOptVal=TRUE;
nReturn=setsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, sizeof(BOOL));
if (nReturn == SOCKET_ERROR)
{
nReturn=WSAGetLastError();
}
// enable reuse of address
bOptVal=TRUE;
nReturn=setsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, sizeof(BOOL));
if (nReturn == SOCKET_ERROR)
{
nReturn=WSAGetLastError();
}
// get the socket's max message size
int nOptSize=sizeof(UINT);
UINT nMaxMsgSize=600;
nReturn=getsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&nMaxMsgSize, &nOptSize);
if (nReturn == SOCKET_ERROR)
{
nReturn=WSAGetLastError();
nMaxMsgSize=600; // default max size
}
nMaxIpIpxBuf=nMaxMsgSize; // always create buffer that is as big as the sockets max message size
pbyIpIpxRxBuf = new char[nMaxIpIpxBuf]; // allocate buffer for receiving data from socket
if (!pbyIpIpxRxBuf)
bDone = TRUE;
else
memset(pbyIpIpxRxBuf,0,nMaxIpIpxBuf*sizeof(char));
// bind to address
nReturn=bind(lpRTD->m_Socket, &saRx.sa, cbAddr);
if (nReturn == SOCKET_ERROR)
{
nReturn = AddSocketErrorToEventViewer(lpRTD);
bDone = TRUE;
}
// send data to indicate startup
if (lpRTD->m_eProtocol == V7_RTD_ENHANCED)
{
int nLen=lpRTD->BuildErrorMsg(V7_ERTD_SERVICE_STARTUP, szErrorCode, sizeof(szErrorCode));
nReturn=sendto(lpRTD->m_Socket,szErrorCode,nLen, nFlags, &lpRTD->m_saRTD.sa, cbAddr);
if (nReturn == SOCKET_ERROR)
{
nReturn=WSAGetLastError();
}
}
} // end if not done
}
Main()
nFromLen = cbAddr;
nReturn=recvfrom(lpRTD->m_Socket, pbyIpIpxRxBuf, nMaxIpIpxBuf, nFlags, &saFrom.sa, &nFromLen);
if(nReturn == SOCKET_ERROR)
{
SetupSocket(lpRTD, bDone, saRx, nRTDPort, saFrom, cbAddr, dwLocalAddress, nMaxIpIpxBuf, pbyIpIpxRxBuf,nFlags, FALSE);
nReturn=recvfrom(lpRTD->m_Socket, pbyIpIpxRxBuf, nMaxIpIpxBuf, nFlags, &saFrom.sa, &nFromLen);
}
// if i take this out no error....
nReturn=sendto(lpRTD->m_Socket, szErrorCode, nLen, nFlags, &saFrom.sa, cbAddr);

setsockopt: Bad file descriptor in C++

I have the famous error "address already in use" because I have no check for the bind function.
Here is my code:
memset(&(this->serv_addr), 0, sizeof(this->serv_addr));
this->serv_addr.sin_family = AF_INET;
this->serv_addr.sin_port = htons(port);
this->serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int yes = 1;
if (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
But running code I got this:
setsockopt: Bad file descriptor
The code is right, from the guide Beejnet.
But why I got the error?
Maybe the position of the code is wrong?
The first the that sock_fd is called is in the function w_socket:
int retv;
retv = socket(AF_INET, SOCK_STREAM, 0);
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[socket] " + err_msg;
throw err_msg;
}
else
{
int reuse_opt = 1;
setsockopt(this->sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_opt, sizeof(int));
return retv;
}
}
By default there's the sesockopt but no check.
I've tried but it doesn't work.
You need to first create the socket via the socket call, like:
sock_fd = socket(PF_INET, SOCK_STREAM, 0);
(and check the return value; see man 2 socket for details)
Only then you may do your setsockopt call. Before the call to socket, your sock_fd variable will contain a random value (or 0) instead of a socket file descriptor.
Edit after updated question:
Your call to setsockopt needs to use retv instead of this->sock_fd as at that point in time, the this->sock_fd variable is not yet containing the result of your call to socket.