Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

errno 48 on bind() call

I am trying to open a socket connection on a Mac OS laptop to receive data from a process on another (Linux) machine.

I am using the code sequence shown below (slightly edited), which works when both machines are Linux (so I am not showing the other end).

The code is being compiled with gcc on the Mac--no errors or warnings.

The code fails at the bind() call and my error handling code says the system error (errno variable) is 48. There is no perror command on the Mac, but the Linux perror says this error number means "Link number out of range". I cannot find any information on this system error. I am sure that the variable "nrp1" in the code

is equal to 10003, the port I am trying to use here, which the other system understands and which is "unassigned" in /etc/services. Also, the variable fd->URF.SOCK.isfd contains the standard integer file descriptor returned by the socket() call earlier in the code, which is this:

fd->URF.SOCK.isfd = socket(PR_INET, SOCK_STREAM, 0) (and is known to return a nonzero file descriptor).

Any suggestions?


----Relevant code fragment----

struct sockaddr_in initaddr;


int iru = 1; /* To allow fast reuse */
if (setsockopt(fd->URF.SOCK.isfd, SOL_SOCKET, SO_REUSEADDR,
&iru, sizeof(iru)) < 0) { kexit = 8; goto ERROR98; }


memset((char *)&initaddr, 0, sizeof(struct sockaddr_in));
initaddr.sin_family = AF_INET;
if (nrp1 <= 0) { kexit = 4; goto ERROR98; }
initaddr.sin_port = htons(nrp1);
/* Expt added 03/30/16, GNR - INADDR_ANY is 0 on Linux */
initaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd->URF.SOCK.isfd, (struct sockaddr *)&initaddr,
sizeof(initaddr)) < 0)
{ kexit = 5; goto ERROR98ME; }



Thanks, gnreeke

MacBook Pro, OS X El Capitan (10.11.3)

Posted on Apr 5, 2016 3:42 PM

Reply
6 replies

Apr 6, 2016 8:37 AM in response to gnreeke

The answers to your questions are the following:

(1) "What is PR_INET"? That was a typo -- I hand typed this and what I actually have is PF_INET.

(2) "Why I do I think OSX doesn't have perror()?" I didn't mean the perror() system call, I meant the perror command-line program.

If I type "perror 48" into a command-line prompt, I get "Command not found". So I did "perror 48" on the Linux machine to get

the result quoted in my post. So I have to write a program on the Mac to call perror() from a command line??

(3) "Why aren't you using functions like getaddrinfo()?" There are a lot of details I left out of my code snippet which I believed were

irrelevant. What is actually happening is that elsewhere in this program communication with a server I also wrote is initiated. That

server then tries to open a second socket interface with the client to exchange a second stream of information. The code I submitted

is where the client is setting up to listen for this second connection. Right after the bind() call is a listen() call. But the error happens

before it gets to the listen(). INADDR_ANY as I understand it is the correct usage in this case, where we are listening, not initiating a connection.

I am not an OSX programmer, but a fairly experienced Linux programmer. As I indicated, the code works when the client and server are both Linux machines. My understanding is that in its guts, OSX is Unix-like, so I was hoping the same protocols would work there. My understanding is that getaddrinfo() is used to look up the IP address of a host. I already know that address; it is on my local LAN and was used to start up the server in the first place.

As for using AF_INET in the socket call instead of PF_INET, I will try that, although the documentation I have says the first argument should be a protocol type. And I can certainly try IPPROTO_TCP instead of the Linux usage SOCK_STREAM. But I don't see why you want me to use getaddrinfo() when listening for an incoming connection.

Thanks,

gnreeke

Apr 6, 2016 8:50 AM in response to gnreeke

Hello again gnreeke,

OK. That all makes more sense now. Unfortunately, sometimes people post here with some code they've copied and pasted from the internet and they have no idea how the code works, or even networking in general.


I was referring to getaddrinfo() primarily because I had some code handy that was fairly close to the kind of code you are describing and that's what I used. You can provide an IP address to getaddrinfo(). The nice part about that function is that it sets up all of the socket structures correctly. That can be tricky to get get right. It is the kind of thing that might work fine on Linux but mysteriously fail on a Mac. There is a wider range of code that will work on Linux. On the Mac, you have to stay closer to the canonical examples.


But error 48 is address already in use. Your setsockopt() call is not working. Does it work after a reasonable timeout?


OS X is not really UNIX-line "in its guts". Its guts are Mach and it has a number of different compatibility layers. One of those is a BSD layer sufficient to give it official UNIX certification. The trick is to write code that is closer to what said UNIX certification expects. Such code will also work fine in Linux. I know it sounds messy, but I'm actually glossing over the true extent of the messiness.

Apr 6, 2016 9:23 AM in response to etresoft

Dear etresoft,

Thanks, that is very helpful. But here is my new question--what exactly does "address in use" imply. Yes, I already have a socket stream connection set up between client and server (and "ps" on the server machine shows the program has started running). I am trying to set up a second stream on another port (I just use two consecutive port numbers from the "unassigned" ones in /etc/services). I would assume "address in use" maybe means "port in use" because surely more than one connection to the same address is allowed? If the port is really in use, I suppose there is some failed test run that wasn't cleaned up properly and I can look for that. Would netstat tell me this? Can I use setsockopt() to force it to close (assuming I write some code to be sure the server is not in use for another client--I haven't yet done the extra work to handle multiple uses in parallel with different port numbers, but I have named semaphores that will tell me what is going on).

As for "your setsockopt() call is not working" -- well, it must have returned zero, otherwise the test and goto in my code would have produced an error message.

gnreeke

Apr 6, 2016 10:27 AM in response to gnreeke

Hello again gnreeke,

There is some murkiness about what that means. It typically means the port on that address is already in use. Technically, there is also an SO_REUSEPORT option that you could use. Usually you get this error when you are debugging and trying to run the server on the same port over and over again. There is a delay before the OS will release a port. If you exit cleanly, there shouldn't be a delay but when debugging that doesn't always happen. netstat should tell you if the port is still in use.


Normally you would use setsockopt() to reuse the port, but you have already done that. Maybe double check that it really is trying to use a different port. Also check the sequence of code. You want to create the socket and then immediately set the options you want. If you do something else, all bets are off. I'm also not sure about the structures you are passing in to bind(). If those aren't right, all bets are off. It could still work, but not honour the setsockopt(). I'm not saying I know of any specific behaviour like this, I just have a lot of experience writing bad networking code. 🙂


If you are doing something custom, it is usually best to use port 0 and let the OS assign an ephemeral port for you. Print out the port it is using and connect to that on the client side. You could use Bonjour to look up that port and use that same logic in production.


It sounds like this code is part of some larger system but isn't quite ready for that yet. If you add some logging statements and/or manually run the clients and servers, you will probably find the problem pretty quickly.

Apr 6, 2016 1:23 PM in response to etresoft

Dear etresoft,

OK, I didn't know about the lsof command, but using that I could see that the port was open because the listen() was still running from a previous failed test process that was not killed. So I can clear the port and then the bind is OK and I get to my next bug, which I won't bother you with for now. Hopefully I can add to this dialog when I next feel stuck.

Thanks again, gnreeke

errno 48 on bind() call

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.