Taken from the original at http://www.ecst.csuchico.edu/~beej/guide/net/ ... see end of writeup for Copyright statement.
bind()--What port am I on?
Once you have a socket, you might have to associate that socket with a port on your local machine. (This is commonly done if you're going to listen() for incoming connections on a specific port -- MUDs do this when they tell you to "telnet to x.y.z port 6969".) If you're going to only be doing a connect(), this may be unnecessary. Read it anyway, just for kicks.
Here is the synopsis for the bind() system call:
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
sockfd is the socket file descriptor returned by socket(). my_addr is a pointer to a struct sockaddr that contains information about your address, namely, port and IP address. addrlen can be set to sizeof(struct sockaddr).
Whew. That's a bit to absorb in one chunk. Let's have an example:
#define MYPORT 3490
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* do some error checking! */
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(MYPORT); /* short, network byte order */
my_addr.sin_addr.s_addr = inet_addr("188.8.131.52");
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
/* don't forget your error checking for bind(): */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
There are a few things to notice here. my_addr.sin_port is in Network Byte Order. So is my_addr.sin_addr.s_addr. Another thing to watch out for is that the header files might differ from system to system. To be sure, you should check your local man pages.
Lastly, on the topic of bind(), I should mention that some of the process of getting your own IP address and/or port can can be automated:
my_addr.sin_port = 0; /* choose an unused port at random */
my_addr.sin_addr.s_addr = INADDR_ANY; /* use my IP address */
See, by setting my_addr.sin_port to zero, you are telling bind() to choose the port for you. Likewise, by setting my_addr.sin_addr.s_addr to INADDR_ANY, you are telling it to automatically fill in the IP address of the machine the process is running on.
If you are into noticing little things, you might have seen that I didn't put INADDR_ANY into Network Byte Order! Naughty me. However, I have inside info: INADDR_ANY is really zero! Zero still has zero on bits even if you rearrange the bytes. However, purists will point out that there could be a parallel dimension where INADDR_ANY is, say, 12 and that my code won't work there. That's ok with me:
my_addr.sin_port = htons(0); /* choose an unused port at random */
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* use my IP address */
Now we're so portable you probably wouldn't believe it. I just wanted to point that out, since most of the code you come across won't bother running INADDR_ANY through htonl().
bind() also returns -1 on error and sets errno to the error's value.
Another thing to watch out for when calling bind(): don't go underboard with your port numbers. All ports below 1024 are RESERVED! You can have any port number above that, right up to 65535 (provided they aren't already being used by another program.)
One small extra final note about bind(): there are times when you won't absolutely have to call it. If you are connect()'ing to a remote machine and you don't care what your local port is (as is the case with telnet), you can simply call connect(), it'll check to see if the socket is unbound, and will bind() it to an unused local port.
Prev | Up | Next
Copyright © 1995, 1996 by Brian "Beej" Hall. This guide may be reprinted in any medium provided that its content is not altered, it is presented in its entirety, and this copyright notice remains intact. Contact email@example.com for more information.