模型
#include
socket()
//創(chuàng)建網(wǎng)絡端點,返回socket文件描述符,失敗返回-1設errnoint socket(int domain, int type, int protocol);
domain?:協(xié)議族(protocol family)(網(wǎng)絡通訊(IP)還是本地通訊(xxx.socket))
- AF_INET用于實現(xiàn)給予ipv4網(wǎng)絡協(xié)議的網(wǎng)絡協(xié)議
type?:協(xié)議(TCP還是UDP) - SOCK_DGRAM?//數(shù)據(jù)報套接字, 實現(xiàn)包括但不限于UDP協(xié)議, which is不可靠,無連接的數(shù)據(jù)報通信方
protocol: 特殊協(xié)議, 一般給0
準備通信地址:
struct sockaddr{ //主要用于函數(shù)的形參類型, 很少定義結(jié)構(gòu)體變量使用, 叫做通用的通信地址類型//$man bind sa_family_t sa_family; char sa_data[14];}struct sockaddr_in{ //準備網(wǎng)絡通信的通信地址 //$man in.h sa_family_t sin_family; //協(xié)議族, 就是socket()的domain的AF_INET in_port_t sin_port; //端口號 struct in_addr sin_addr; //IP地址, //當前網(wǎng)段的最大ip地址是廣播地址,即,xxx.xxx.xxx.255。 //255.255.255.255在所有網(wǎng)段都是廣播地址}struct in_addr{ in_addr_t s_addr; //整數(shù)類型的IP地址}
bind()
//把通信地址和socket文件描述符綁定,用在服務器端,成功返回0,失敗返回-1設errnoint bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd: socket文件的fd(returned by socket())
addr: 需要強制類型轉(zhuǎn)換成socketaddr_un或soketaddr_in, 參見上
addrlen: 通信地址的大小, 使用sizeof();
sendto()
//向指定的socket和相應的地址發(fā)送消息,成功返回實際發(fā)送數(shù)據(jù)的大小,失敗返回-1設errnossize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
dest_addr:目標地址(收件人信息)
addrlen: 目標地址的大小
ANote
- send(sockfd, buf, len, flags);等價于 sendto(sockfd, buf, len, flags, NULL, 0);
- recv()/ send()表示通過sockfd收發(fā)數(shù)據(jù), 因為tcp下, 收發(fā)之前sockfd已經(jīng)和相應的地址連接了,所以不需要指定收發(fā)誰的/給誰, 但是udp因為收發(fā)時沒有連接, 所以需要指定
recvfrom()
//從指定的socket和相應的地址接受消息,并提供來電顯示的功能,成功返回實際接收的數(shù)據(jù)大小,失敗返回-1設errnossize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
src_addr: 結(jié)構(gòu)體指針, 用于保存數(shù)據(jù)發(fā)送方的通信地址
addrlen: 指針類型, 用于保存發(fā)送方的地址大小
Note:
- recv(sockfd, buf, len, flags); 等價于 recvfrom(sockfd, buf, len, flags, NULL, 0);
- accept() and recvfrom() 后面的參數(shù)是用來提供來電顯示的
- 一個server對應多個client
- server可以不知道client的地址, 但是client得知道server的地址
- send data 一定要知道對方地址
- receive data不需要知道對方地址
- TCP/IP的socket都是SOCK_STREAM的,全程連接,通過socket就能找到對方地址, send data的話,直接丟給socket就行
- UDP/IP的socket是SOCK_DGRAM的,不全程連接,不能通過socket找到對方,send data的話,server中需要使用recvfrom()來知道client的地址, 所以肯定要sendto();client本來就知道server的地址, 直接sendto()
- recvfrom()的唯一意義就是在udp-server中配合sendto()使用
- 因為不能通過socket找到對方, 只要是udp發(fā)消息, 就得通過sendto()
例子-一對一的upd/ip協(xié)議的服務器模型
//udp/ip server 五步走#include
//udp/ip client#include
評論