📄 00000004.htm
字号:
we do in this document. sa_data contains a destination address and port <BR>number for the socket. This is rather unwieldy. <BR>To deal with struct sockaddr, programmers created a parallel structure: <BR>struct sockaddr_in ("in" for "Internet".) <BR> struct sockaddr_in <BR> short int sin_family; /* Address family */ <BR> unsigned short int sin_port; /* Port number */ <BR> struct in_addr sin_addr; /* Internet address */ <BR> unsigned char sin_zero[8]; /* Same size as struct sockaddr */ <BR> ; <BR>This structure makes it easy to reference elements of the socket address. <BR>Note that sin_zero (which is included to pad the structure to the length of <BR>a struct sockaddr) should be set to all zeros with the function bzero() or <BR>memset(). Also, and this is the important bit, a pointer to a <BR>struct sockaddr_in can be cast to a pointer to a struct sockaddr and <BR>vice-versa. So even though socket() wants a struct sockaddr *, you can still <BR> <BR>use a struct sockaddr_in and cast it at the last minute! Also, notice that <BR>sin_family corresponds to sa_family in a struct sockaddr and should be set <BR>to "AF_INET". Finally, the sin_port and sin_addr must be in Network Byte <BR>Order! <BR>"But," you object, "how can the entire structure, struct in_addr sin_addr, <BR>be in Network Byte Order?" This question requires careful examination of the <BR> <BR>structure struct in_addr, one of the worst unions alive: <BR> /* Internet address (a structure for historical reasons) */ <BR> struct in_addr <BR> unsigned long s_addr; <BR> ; <BR>Well, it used to be a union, but now those days seem to be gone. Good <BR>riddance. So if you have declared "ina" to be of type struct sockaddr_in, <BR>then "ina.sin_addr.s_addr" references the 4 byte IP address (in Network Byte <BR> <BR>Order). Note that even if your system still uses the God-awful union for <BR>struct in_addr, you can still reference the 4 byte IP address in exactly the <BR> <BR>same way as I did above (this due to #defines.) <BR>---------------------------------------------------------------------------- <BR> <BR>5. Convert the Natives! <BR>We've now been lead right into the next section. There's been too much talk <BR>about this Network to Host Byte Order conversion--now is the time for <BR>action! <BR>All righty. There are two types that you can convert: short (two bytes) and <BR>long (four bytes). These functions work for the unsigned variations as well. <BR> <BR>Say you want to convert a short from Host Byte Order to Network Byte Order. <BR>Start with "h" for "host", follow it with "to", then "n" for "network", and <BR>"s" for "short": h-to-n-s, or htons() (read: "Host to Network Short"). <BR>It's almost too easy... <BR>You can use every combination if "n", "h", "s", and "l" you want, not <BR>counting the really stupid ones. For example, there is NOT a stolh() ("Short <BR> <BR>to Long Host") function--not at this party, anyway. But there are: <BR> * htons()--"Host to Network Short" <BR> * htonl()--"Host to Network Long" <BR> * ntohs()--"Network to Host Short" <BR> * ntohl()--"Network to Host Long" <BR>Now, you may think you're wising up to this. You might think, "What do I do <BR>if I have to change byte order on a char?" Then you might think, "Uh, never <BR>mind." You might also think that since your 68000 machine already uses <BR>network byte order, you don't have to call htonl() on your IP addresses. You <BR> <BR>would be right, BUT if you try to port to a machine that has reverse network <BR> <BR>byte order, your program will fail. Be portable! This is a Unix world! <BR>Remember: put your bytes in Network Order before you put them on the <BR>network. <BR>A final point: why do sin_addr and sin_port need to be in Network Byte Order <BR> <BR>in a struct sockaddr_in, but sin_family does not? The answer: sin_addr and <BR>sin_port get encapsulated in the packet at the IP and UDP layers, <BR>respectively. Thus, they must be in Network Byte Order. However, the <BR>sin_family field is only used by the kernel to determine what type of <BR>address the structure contains, so it must be in Host Byte Order. Also, <BR>since sin_family does not get sent out on the network, it can be in Host <BR>Byte Order. <BR>---------------------------------------------------------------------------- <BR> <BR>6. IP Addresses and How to Deal With Them <BR>Fortunately for you, there are a bunch of functions that allow you to <BR>manipulate IP addresses. No need to figure them out by hand and stuff them <BR>in a long with the << operator. <BR>First, let's say you have a struct sockaddr_in ina, and you have an IP <BR>address "132.241.5.10" that you want to store into it. The function you want <BR> <BR>to use, inet_addr(), converts an IP address in numbers-and-dots notation <BR>into an unsigned long. The assignment can be made as follows: <BR> ina.sin_addr.s_addr = inet_addr("132.241.5.10"); <BR>Notice that inet_addr() returns the address in Network Byte Order <BR>already--you don't have to call htonl(). Swell! <BR>Now, the above code snippet isn't very robust because there is no error <BR>checking. See, inet_addr() returns -1 on error. Remember binary numbers? <BR>(unsigned)-1 just happens to correspond to the IP address 255.255.255.255! <BR>That's the broadcast address! Wrongo. Remember to do your error checking <BR>properly. <BR>All right, now you can convert string IP addresses to longs. What about the <BR>other way around? What if you have a struct in_addr and you want to print it <BR> <BR>in numbers-and-dots notation? In this case, you'll want to use the function <BR>inet_ntoa() ("ntoa" means "network to ascii") like this: <BR> printf("%s",inet_ntoa(ina.sin_addr)); <BR>That will print the IP address. Note that inet_ntoa() takes a struct in_addr <BR> <BR>as an argument, not a long. Also notice that it returns a pointer to a char. <BR> <BR>This points to a statically stored char array within inet_ntoa() so that <BR>each time you call inet_ntoa() it will overwrite the last IP address you <BR>asked for. For example: <BR> char *a1, *a2; <BR> . <BR> . <BR> a1 = inet_ntoa(ina1.sin_addr); /* this is 198.92.129.1 */ <BR> a2 = inet_ntoa(ina2.sin_addr); /* this is 132.241.5.10 */ <BR> printf("address 1: %s",a1); <BR> printf("address 2: %s",a2); <BR>will print: <BR> address 1: 132.241.5.10 <BR> address 2: 132.241.5.10 <BR>If you need to save the address, strcpy() it to your own character array. <BR>That's all on this topic for now. Later, you'll learn to convert a string <BR>like "whitehouse.gov" into its corresponding IP address (see DNS, below.) <BR>---------------------------------------------------------------------------- <BR> <BR>7. socket()--Get the File Descriptor! <BR>I guess I can put it off no longer--I have to talk about the socket() system <BR> <BR>call. Here's the breakdown: <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -