並發服務器
迭代服務器 iterative server 單進程
並發服務器 concurrent server 多進程
當連接建立時,accept返回,服務器調用fork
子進程為客戶提供服務(通過connfd已連接套接口),
父進程等待另一個連接(通過listenfd監聽套接口)。
子進程開始處理新客戶,父進程便關閉已連接套接口。
accept 返回前/客戶-服務器的狀態
fork返回客戶-服務器的狀態
父子進程關閉相應套接口客戶-服務器狀態
父進程connfd的close不會終止它與客戶的連接:
每個文件或套接口都有一個訪問計數,該訪問計數在文件表項中維護,它表示當前指
向該文件或套接口的打開的描述字個數。
從sock返回,與listenfd關聯的文件表項訪問計數值為1,
從accept返回,與connfd關聯的文件表項訪問計數值也為1。
當fork返回,兩個描述字在父進程與子進程間共享(duplicated)與兩個套接門相關
聯的文件表項訪問計數值均為2。
當父進程關閉connfd時,只是將訪問計數值從2減為1。描述字只在訪問計數值達到0時
才真正關閉,這在面某個時候子進程關閉connfd時會碰上.
close 函數
功能:將套接口做上“已關閉的標記”,並立即返回進程。
將套接口描述字的訪問計數器減1。
當訪問計數器值為0時,引發TCP的四個分組連接終止序列,從而關閉套接口。
定義:
#include <sys/unistd.h>
int close(int sockfd);
getsockname 和 getpeername函數
功能:
getsockname: 返回本地協議地址
getpeername:返回遠程協議地址
定義:
#include <sys/unistd.h>
int getsockname (int sockfd, struct sockaddr *localaddr, int *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, int *addrlen);
一個示例程序:
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#define MYPORT 3490 /* the port users will be connecting to */
#define BACKLOG 10 /* how many pending connections queue will hold */
main()
{
int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */
struct sockaddr_in my_addr; /* my address information */
struct sockaddr_in their_addr; /* connector's address information */
int sin_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* do some error checking! */
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(MYPORT); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
/* don't forget your error checking for these calls: */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
listen(sockfd, BACKLOG);
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, &their_addr, &sin_size);
. . . . . . . . . . . . .
(http://www.fanqiang.com)
進入【