先看这样一段程序:
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 150
int main()
{
struct sockaddr_in serv;
char buff[BUFFSIZE];
int sockfd, n;
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
perror("socket error");
bzero((char *) &serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("192.168.1.104");
serv.sin_porr = htons(13);
r in final launch sequence
Failed to execute MI command:
maintenance set python print-stack off
Error message from debugger back end:
Undefined maintenance set command: "python print-stack off". Try "help maintenance set".
Undefined maintenance set command: "python print-stack off". Try "help maintenance set".
if (sendto(sockfd, buff, BUFFSIZE, 0,
(struct sockaddr *) &serv, sizeof(serv)) != BUFFSIZE)
perror("sendto error");
if ((n = recvfrom(sockfd, buff, BUFFSIZE, 0,
(struct sockaddr *) NULL, (int *)NULL )) < 2)
perror("recvfrom error");
buff[n-2] = 0;
printf("%s\n", buff);
exit(0);
}
makefile:
1.5:1.5.o
gcc -o 1.5 1.5.o
1.5.o:1.5.c
gcc -c -o 1.5.o 1.5.c
clean:
rm 1.5 1.5.o
看这句代码:
int sockfd, n;
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
socket系统调用返回一个描述符.
在tcp/ip详解卷二的1.8节对descriptor有详细解释:
chapter 1.8:descriptors
The return value from socket is a descriptor that shares all the properties of other unix descriptors: read and write can be called for the descriptor, you can dup it, it is shared by the parent and child after a call to fork, its properties can be modified by calling fcntl, it can be closed by calling close, and so on. We see our example that the socket descriptor is the first argument to both the sendto and recvfrom functions. When our program terminates by calling exit, all open descriptors including the socket descriptor and closed by the kernel.
We now introduce the data structures that are created by the kernel when the process calls socket.
Everything starts with the process table entry for the process. One of these exists for each process during its lifetime.
A descriptor is an index into an array within the process table entry for the process. This array entry points to an open file table structrue, which in turn points to an i-node or v-node structure that describes the file. Figure below summarizes this relationship.
更详细一点:
1.when the process executes a system call, such as sendto, the kernel starts with the descriptor value and uses fd_ofiles to index into the vector of file structure pointers,ending up with the file structure for the descriptor. The file structure points to the socket structure, which points to the inpcb structure.
2.when a udp datagram arrives on a network interface, the kernel searches through all the udp protocol control blocks to find the appropriate one, minimally based on the destination udp port number and perhaps the destination IP address, source ip address, and source port numbers too. Once the inpcb structure is located the kernel finds the corresponding socket structure through the inp_socket pointer.
The inpcb{}结构成员有:
inp_next
inp_pre
inp_faddr
inp_fport
inp_laddr
inp_socket
The members inp_faddr and inp_laddr contains the foreign and local ip addresses, and the members inp_fport and inp_lport contains the foreign and local port numbers. The combination of the local ip address and the local port number is often called a socket, as is the combination of the foreign IP address and the foreign port number.
There are 3 points to understand:
1.the call to socket by our process ends up allocating the lowest unused descriptor. This descriptor is used by the process in all subsequent system calls that refer to this socket.
2.The following kernel structures are allocated and linked togethter: a file structure of type DTYPE_SOCKET, a socket structure, and an inpcb structure.Lots of initialization is performed on these structures that we don’t show: the file structure is marked for read and write since the call to socket alway returns descriptor that can be read or written. The default sizes of the input and output buffers are set in the socket structure, and so on.
3.We showed nonsocket descriptors for our standard input, output, and error to show that all descriptors ends up at a file structure, and it is from that point on that differences appear between socket descriptors and other descripors.