1. 程式人生 > >Socket編程(day14)

Socket編程(day14)

socket 監聽 host 等待 spa add 多路復用 設備 所有

一、基於TCP傳輸層的編程模型
TCP是面向連接的,安全可靠的。
三次握手
服務器端編程模型
1、創建一個用於網絡通訊的設備 通訊端點
socket(2)
#include  <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:創建一個用於通訊的端點
參數:
domain:
AF_INET:應用於IPV4地址家族的
AF_INET6:應用於IPV6地址家族的
type:
SOCK_STREAM:可靠的、基於連接的 雙向的、隊列式的 TCP
SOCK_DGRAM:支持數據包    不可靠的  無連接的  UDP

protocol:
0 返回值: -1 錯誤 errno被設置 返回一個新的文件描述符 2、將這個通訊端點和本機的ip地址、端口號做綁定 bind(2) int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 功能:綁定名字到地址。創建socket以後,socket中有地址空間但是沒有具體地址放在這個地址空間。需要將具體的地址和socket的地址空間綁定。 參數: sockfd:已經創建好的socket,但是這個socked沒有具體的地址 addr:指定了具體的地址,將這個地址綁定到sockfd中 addrlen:指定了addr的大小、字節數 返回值:
0 成功 -1 錯誤 errno被設置 地址家族的通用結構 struct sockaddr{ sa_family_t sa_family; char sa_data[14]; }; ipv4和ipv6 man in.h #include <netinet/in.h> in_port_t uint16_t in_addr_t uint32_t sa_family_t <sys/socket.h> struct in_addr{ in_addr_t s_addr; }; ipv4的具體地址 struct
sockaddr_in{ sa_family_t sin_family; //AF_INET. in_port_t sin_port; //Port number. struct in_addr sin_addr; //IP address. }; INADDR_ANY IPv4 local host address 這是一個宏,宏的本質是一個整數。代表了本機的所有的地址。 端口號 0~65535 但是5000以下最好不要用。因為已經被國際組織使用了。 sin_port 采用網絡字節序 需要將本機字節序的數字轉換為網絡字節序 系統提供了函數。處理本機字節序和網絡字節序的問題 #include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); h host n net s short l long to ip地址 字符串格式 二進制格式 互相轉換 inet_pton(3) #include <arpa/inet.h> int inet_pton(int af, const char *src, void *dst); 功能:從字符串格式轉換為二進制格式 IPV4 IPV6 參數: af: AF_INET or AF_INET6 src:字符串格式的ip地址 dst:存儲了網絡地址結構的信息 返回值: 1 成功 0 src無效 -1 錯誤 errno被設置 struct in_addr #include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); 功能:二進制到字符串的轉化 參數: af: AF_INET or AF_INET6 src: struct in_addr dst:用來存儲字符串的空間 size:指定了空間的有效字節數 返回值: NULL 錯誤 errno被設置 非空 返回dst的地址,字符串的首地址。 ip地址 127.0.0.1 本地地址 環回地址 測試機器的網絡設備工作是否正常。 setsockopt(2) 3、在這個通訊端點上監聽客戶端連接的到來,如果有連接的到來,將到達的連接存放在緩沖區中(隊列的數據結構) listen(2) int listen(int sockfd, int backlog); 功能:在socket監聽連接。將sockfd標記為被動連接。接收即將到來的客戶端請求。 參數: sockfd:指定了被監聽的socket backlog:指定了未決連接的最大數。 返回值: 0 成功 -1 錯誤 errno被設置 4、從這個緩沖區隊列中取出一個客戶端連接,返回一個連接描述符用於和客戶端的通訊。(這個連接描述符稱為conn_fd) accept(2) int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 功能:在socket上接收一個連接 參數: sockfd:指定了監聽的socket addr:在這個地址空間裏填充了客戶端的地址和端口號 addrlen:空間裏指定了addr的長度。如果addr為NULL,那麽也要設置為NULL 返回值: -1 錯誤 errno被設置 返回一個非負的整數,就是連接描述符 5、使用conn_fd和客戶端通訊 (1)獲取客戶端的請求 read(2) (2)處理客戶端請求 (3)響應客戶端 write(2) 6、關閉conn_fd,終止和客戶端的通訊 close(conn_fd); 客戶端的編程模型 1、創建一個用於通訊的設備(通訊端點) socket(2) 2、使用這個端點連接到服務器(IP地址和端口號) connect(2) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 功能:在socket上發起一個連接 參數: sockfd:指定socket,將這個socket連接到addr的地址空間 addr:指定具體的地址空間,要連接到的地址空間。server addrlen:指定了addr的長度 返回值: 0 成功 -1 錯誤 errno被設置 3、向服務器發送消息 4、等待服務器端的響應消息 5、處理服務器的響應消息 6、關閉設備,結束本次通訊。 舉例說明 編寫基於TCP的通訊模型 服務器端代碼 參見 server.c 客戶端代碼參見 client.c 172.30.3.93 二、並發服務器的實現 三種方法實現服務器的並發 多進程 多線程 多路復用 使用多進程實現服務器的並發功能 什麽時候?什麽地方?子進程才登場。 fork(2) 子進程負責的任務 子進程負責和客戶端的通訊 關閉s_fd。 信息處理 關閉和客戶端的連接 父進程負責的任務 父進程負責從未決連接隊列中取出一個連接,創建和客戶端通訊的文件描述符 創建子進程 關閉和客戶端的連接 負責對子進程收屍。非阻塞收屍

Socket編程(day14)