Monday, July 13, 2009

ネットワークプログラミング - メモ

■ Byte order
#include <arpa/inet.h&st;
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

■ bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
struct sockaddr{
unsigned short sa_family;
char sa_data[14];
}
■ IPソケットアドレス関連の構造体
struct sockaddr_in {
sa_family_t sin_family; // address family: AF_INET
in_port_t sin_port; // port in network byte order
struct in_addr sin_addr; // internet address
}
// Internet address
struct in_addr{
uint32_t s_addr; // address in network byte order
}
※sockaddr と sockaddr_in は同じもので,互換性を保つためにある.
実際よく使うのは sockaddr_in で,sockaddr_in からIPアドレスを取得できる(struct in_addr で)

■ インターネットアドレス操作
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
in_addr_t inet_network(const char *cp);
char *inet_ntoa(struct in_addr in);
struct in_addr inet_makeaddr(int net, int host);
in_addr_t inet_lnaof(struct in_addr in);
in_addr_t inet_netof(struct in_addr in);

typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr;
}
■ gethostbyname, gethostbyaddr
#include <netdb.h>
extern int h_errno;

struct hostent *gethostbyname(const char *name);

#include <sys/socket.h>
struct hostent *gethostbyaddr(const void *addr,socklen_t len, int type);
struct hostent *gethostent(void);

struct hostent {
char *h_name; // official name of host
char **h_aliases; // alias list
int h_addrtype; // host address type
int h_length; // length of address
char **h_addr_list; // list of addresses
}
#define h_addr h_addr_list[0]

gethostbyname(), gethostbyaddr()の代わりに
getaddrinfo(3), getnameinfo(3)を使うべき
■ getaddrinfo, getnameinfo
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);

void freeaddrinfo(struct addrinfo *res);
const char *gai_strerror(int errcode);

struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};

■ shutdown() 関数
この関数を使用してTCPでコネクションを閉じるが,注意しないといけないのはこの関数は正常なコネクション切断のときにしか使えない.
例えば:クライアントから接続してきて(accept()),forkで分岐
親プロセスではクライアントのソケットは使わないため,そのソケットを閉じるべきが(変にいじってほしくないから),このときshutdown()関数を使用すると,分岐した子プロセスではそのクライアントのソケットを使えなくなる.なのでこの場合は親プロセスではshutdown()ではなく,普通にclose()関数でソケットを閉じる.