CSAPP笔记(十一) 网络编程

深入理解计算机系统

套接字

网络上IP和端口采用大端

// IP地址结构
struct in_addr {
    unsigned int s_addr; //1.2.3.4 -> 0x04030201
};
//DNS主机条目结构
struct hostent {
    char *h_name; // "localhost"
    char **h_aliases; // Null-terminated array of domain names
    int h_addrtype; // AF_INET
    int h_length; // 32
    char **h_addr_list; // Null-terminated array of in_addr structs
};
//常规socket地址结构
struct sockaddr {
    unsigned short sa_family; // Protocol family
    char sa_data[14]; // Address data.
};
//网络socket地址结构
struct sockaddr_in {
    unsigned short sin_family; //AF_INET
    unsigned short sin_port; // 端口
    struct in_addr sin_addr; //IP
    unsigned char sin_zero[8];
};

int socket(int domain, int type, int protocol);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);

// 客户端
int open_clientfd(char *hostname, int port){
        int clientfd;
        struct hostent *hp;
        struct sockaddr_in serveraddr;

        if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                return -1;
        if ((hp = gethostbyname(hostname)) == NULL)
                return -2;
        bzero((char *) &serveraddr, sizeof(serveraddr));
        serveraddr.sin_family = AF_INET;
        bcopy((char *)hp->h_addr_list[0],
              (char *)&serveraddr.sin_addr.s_addr, hp->h_length);
        serveraddr.sin_port = htons(port); // (80=0x0050) => 0x5000
        // 阻塞
        if (connect(clientfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
                return -1;
        return clientfd;
}
//服务端
int open_listenfd(int port){
        int listenfd, optval=1;
        struct sockaddr_in serveraddr;

        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                return -1;
        if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,(const void *)&optval, sizeof(int)) < 0)
                return -1;

        bzero((char *) &serveraddr, sizeof(serveraddr));
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0 -> 0x00000000
        serveraddr.sin_port = htons((unsigned short)port); // 80 -> 0x5000
        if (bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
                return -1;
        if (listen(listenfd, 1024) < 0)
                return -1;
        return listenfd;
}