顯示具有 Unix Network Programming 標籤的文章。 顯示所有文章
顯示具有 Unix Network Programming 標籤的文章。 顯示所有文章

2008年1月25日 星期五

signal

某有事件發生時就會發出signal通知Process,而Process就必須來處理這些signal。
signal可以由Process到另一個Process,或是由Kernel到Process。
我們可以自行定義signal handler來處理各個不同的signal。

系統雖有signal()的function來讓我們指定signal對應的signal handler。然而,由於沒有統一的標準,所以各家UNIX實作上會有所不同,會造成相容性的問題。所以POSIX規範要使用sigaction()這個function。然而sigaction()使用上較signal()複雜。

2007年11月26日 星期一

Concurrent Server

Server可以分為兩種型態,iterativeconcurrent
iterative server一次服務一個使用者,所以若其中某個使用者的服務時間過久,會影響到整個效能。而concurrent server則是可以同時服務多個使用者,最簡單的方法可以利用fork來產生child process來達成此目的。下面則為簡單的範例。

pid_t pid;
int listenfd, connfd;

listenfd = socket( ... );
bind(listenfd, ... );
listen(listenfd, 5);
for (; ;) {
connfd = accept (listenfd, ... );
if((pid = fork()) == 0) {
close(listenfd);
handle the connection
close(connfd);
exit(0);
}
close(connfd); // 由於fork產生的child process會讓connfd的reference counter多1,要記得關掉
}

2007年11月24日 星期六

fork

如何寫一個concurrent server?我們可以使用fork這個function來達成,定義於"unistd.h",用法如下:
pid_t fork(void);

呼叫fork()會產生一個child process,在呼叫fork()指令之前所有parent process開啟的descriptors會與child processs共享。至於如何分辨parent還是child,則依呼叫fork()後的回傳值決定,parent會收到child的Process ID,而child則會收到0。因為,兒子只有一個父親,只要呼叫getppid即可取得父親的PID,而父親可能會有很多的兒子,所以需要記錄每一個兒子的PID。

fork有兩種使用方法:

  1. Process複製自己一份,讓其中一個處理某一個運算,另一個則是做其它事。
  2. Process想執行其它程式,當呼叫fork時會複製一份child process,然後child process執行exec用新程式來取代目前的程式。

2007年11月6日 星期二

IP位址轉換

如何將人讀的140.120.*.*的IP轉換成network byte order的兩進位表示,可以使用以下的函式(定義於"arpa/inet.h">:

// String to 32-bit binary
int inet_aton(const char *strptr, struct in_addr *addrptr);
// 32-bit binary to String
char *inet_ntoa(struct in_addr inaddr);

然而,以上的函式不能處理IPv6的問題,因此有另外兩個函式可以同時處理IPv4與IPv6:

int inet_pton(int family, const char *strptr, void *addrptr);
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

其中當處理IPv4時,family值為AF_INET,IPv6時則為AF_INET6。
inet_ntoa裡,size_t len為回傳string的長度,避免Overflow。
"netinet/in.h"有定義兩個常數,讓我們可以使用他來設定長度。
#define INET_ADDRSTRLEN 16 /* for IPv4 dotted-decimal */
#define INET6_ADDRSTRLEN 46 /* for IPv6 hex string */

2007年11月5日 星期一

Network Byte Order

Internet Protocols是採用Big-endian,因此有四個函式(定義於"netinet/in.h")可供我們轉換host byte order <--> network byte order

uint16_t htons(uint16_t host16bitvalue) ; // host to network short
uint32_t htonl(uint32_t host32bitvalue) ;
// host to network long

uint16_t ntohs(uint16_t net16bitvalue) ; // network to host short
uint32_t ntohl(uint32_t net32bitvalue) ;
// network to host long


當處理port的時候,可以使用hotns()和ntohs()
當處理IPv4位址,可以使用hotnl()和ntohl()

2007年11月3日 星期六

Value-Result

Socket address sturcture總是以reference(指標指向結構)傳進socket函式,而結構的大小也會被傳入。然而長度傳入的方法取決於process to kernel或是kernel to process

Process to Kernel(bind, connect, sendto)

struct sockaddr_in serveraddr;

bind(sockfd, (Struct sockaddr *) &serveraddr, sizeof(serveraddr));

長度的資訊是用來告訴該copy多少資料從process到kernel


Kernel to Process(accept, recvfrom, getsockname, getpeername)

struct sockaddr_in clientaddr;
socklen_t letngth;

length = sizeof(clientaddr);
getpeername( sockfd, (Struct sockaddr*) &clientaddr, &length)

其中,長度的值會改變。用指標傳入,告訴kernel所傳入的struture大小。而當函式結束時,會回傳kernel儲存多少資料在structure,將值存在length上。像length這種參數稱為value-result參數。

2007年11月1日 星期四

Socket Address Structure

IPv4與IPv6的Socket Address Structure定義於"netinet/in.h"裡。

IPv4 Socket address structure: sockaddr_in

/* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr;
};

/* Structure describing an Internet socket address. */
struct sockaddr_in {
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8]; /* Padding */
};

/* IPv6 address */
IPv6 Socket address structure: sockaddr_in6
struct in6_addr {
uint8_t s6_addr[16];
};
struct sockaddr_in6 {
uint8_t sin6_len;
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port;
uint32_t sin6_flowinfo
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};