sp; perror("gethostbyname()"); exit(1); } (void) memset(&serverName, 0, sizeof(serverName)); (void) memcpy(&serverName.sin_addr, hostPtr->h_addr, hostPtr->h_length); /* *h_addr是h_addr_list[0]的同义词, * h_addr_list是一组地址的数组 *长度为4(byte)代表一个IP地址的长度 */ /* * 为了使服务器绑定本机所有的IP地址, * 上面一行代码需要用下面的代码代替 * serverName.sin_addr.s_addr=htonl(INADDR_ANY); */ serverName.sin_family = AF_INET; /* htons:h(host byteorder,主机字节序) * to n(network byteorder,网络字节序 * s(short类型) */ serverName.sin_port = htons(port); /* 在一个地址(本例中的serverSocket)被建立后 * 它就应该被绑定到我们获得的套接口。 */ status = bind(serverSocket, (struct sockaddr *) &serverName, sizeof(serverName)); if (-1 == status) { perror("bind()"); exit(1); } /* 现在套接口就可以被用来监听新的连接。 * BACK_LOG指定了未决连接监听队列(listen queue for pending connections) * 的最大长度。当一个新的连接到达,而队列已满的话,客户就会得到连接拒绝错误。 * (这就是dos拒绝服务攻击的基础)。 */ status = listen(serverSocket, BACK_LOG); if (-1 == status) { perror("listen()"); exit(1); } /* 从这里开始,套接口就开始准备接受请求,并为他们服务。 * 本例子是用for循环来达到这个目的。一旦连接被接受(accpepted), * 服务器可以通过指针获得客户的地址以便进行一些诸如记录客户登陆之类的 * 任务。 for (;;) { struct sockaddr_in clientName = { 0 }; int slaveSocket, clientLength = sizeof(clientName); (void) memset(&clientName, 0, sizeof(clientName)); slaveSocket = accept(serverSocket, (struct sockaddr *) &clientName, &clientLength); if (-1 == slaveSocket) { perror("accept()"); exit(1); } childPid = fork(); switch (childPid) { case -1: /* ERROR */ perror("fork()"); exit(1); case 0: /* child process */ close(serverSocket); if (-1 == getpeername(slaveSocket, (struct sockaddr *) &clientName, &clientLength)) { perror("getpeername()"); } else { printf("Connection request from %s\n", inet_ntoa(clientName.sin_addr)); } /* * Server application specific code * goes here, e.g. perform some * action, respond to client etc. */ write(slaveSocket, MESSAGE, strlen(MESSAGE)); /* 也可以使用带缓存的ANSI函数fprint, * 只要你记得必要时用fflush刷新缓存 */ close(slaveSocket); exit(0); default: /* parent process */ close(slaveSocket);/* 这是一个非常好的习惯 * 父进程关闭子进程的套接口描述符 * 正如上面的子进程关闭父进程的套接口描述符。 */ } } return 0; }
上一页 [1] [2] |