第1步:了解用到的结构体
struct sockaddr_in {
unsigned short sin_family; //AF_INET
unsigned short sin_port; //port
struct in_addr sin_addr;
unsigned char sin_zero[8];
} //#include <socket.h>
这个结构体是网络套接字,在我们应用中,要把他转换成套接字sockaddr,其实内容都是一样的,但是c库使用的是sockaddr,所以我们也没办法
struct sockaddr{
unsigned short sa_family;
char sa_data[14];
}
为了使用方便,我们做如下定义:
typedef struct sockaddr SA;
struct in_addr{
unsigned int s_addr; //netwirk byte order
} //#include <netinet/in.h>
s_addr是32位无符号数,跟我们常说的IP地址是不同的,但可以互相转换,函数为inet_aton()(#include <arpa/inet.h>);
转换完毕后,再用htonl()(#include <netinet/in.h>)函数把32位数转换成网络字节序(就是我们所说的大端)
#define RIO_BUFSIZE 8192
typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];
}rio_t
这个结构体是RIO读写函数所用到的
第二步: 主函数
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
/* Check command line args */
//如果运行时,没有输入端口号作为参数,程序就给出提示后退出
if (argc != 2) {
fprintf(stderr, "usage: %s <port>/n", argv[0]);
exit(1);
}
//把输入的端口号转成整形
port = atoi(argv[1]);
//Open_listenfd( )是自定义的函数,以后介绍,目的是侦听端口
listenfd = Open_listenfd(port);
//进入死循环
while (1) {
//计算结构体大小,即使你看出了结构体需要的字节数,也最好用这种方法,因为存在对齐,不同体系结构可能需要的空间不同
clientlen = sizeof(clientaddr);
//经过封装的Accept函数,没有连接时会阻塞
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
//处理一个HTTP事务
doit(connfd);
//关闭连接
Close(connfd);
}
}