套接字有三种类型:流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM)及原始套接字。
socket()
|
bind()
|
listen()
| socket()
accept() |
| connect()
| |
read() write()
| |
write() read()
| |
close() close()
socket()
|
bind()
| socket()
| |
| bind()
recvfrom() |
| <--------- sendto()
| |
sendto() -----> recvfrom()
| |
close() close()
struct sockaddr {
unsigned short sa_family; /* address族, AF_xxx */
char sa_data[14]; /* 14 bytes的协议地址 */
};
sa_family 一般来说,都是“AFINET”。
sa_data 包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一切的。为了处理struct sockaddr, 程序员建立了另外一个相似的结构 struct sockaddr_in:
struct sockaddr_in (“in” 代表 “Internet”)
struct sockaddr_in {
short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* Internet地址 */
unsigned char sin_zero[8]; /* 添0(和struct sockaddr一样大小)*/
};
这个结构提供了方便的手段来访问socket address(struct sockaddr)结构中的每一个元素。注意sin_zero[8] 是为了是两个结构在内存中具有相同的尺寸,使用sockaddr_in 的时候要把sin_zero 全部设成零值(使用bzero()或memset()函数)。而且,有一点很重要,就是一个指向struct sockaddr_in 的指针可以声明指向一个sturct sockaddr 的结构。所以虽然socket() 函数需要一个structaddr * ,你也可以给他一个sockaddr_in * 。注意在structsockaddr_in 中,sin_family 相当于在 struct sockaddr 中的sa_family,需要设成“AF_INET”。
最后一定要保证sin_port 和sin_addr 必须是网络字节顺序。
/* 因特网地址 (a structure for historical reasons) */
struct in_addr {
unsigned long s_addr;
};
如果你声明了一个“ ina ” 作为一个struct sockaddr_in 的结构, 那么“ina.sin_addr.s_addr”就是4 个字节的IP 地址(按网络字节顺序排放)。需要注意的是,即使你的系统仍然使用联合而不是结构来表示struct in_addr,你仍然可以用上面的方法得到4 个字节的IP 地址。
在struct sockaddr_in 中的sin_addr和sin_port他们的字节顺序都是网络字节顺序,而sin_family却不是网络字节顺序的。
ina.sin_addr.s_addr = inet_addr(“166.111.69.52”);
inet_addr() 返回的地址已经是网络字节顺序了,你没有必要再去调用htonl() 函数。
printf(“%s”, inet_ntoa(ina.sin_addr));
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain , int type , int protocol);
AF_INET
SOCK_STREAM、SOCK_DGRAM
0
错误返回-1,全局变量errno被设置为错误码。
#include <sys/types.h>
#include <sys/socket.h>
int bind (int sockfd , struct sockaddr *my_addr , int addrlen) ;
sockfd 是由socket()函数返回的套接字描述符。
my_addr 是一个指向struct sockaddr 的指针,包含有关你的地址的信息:名称、端口和IP 地址。
addrlen 可以设置为sizeof(struct sockaddr)。
#include <sys/types.h>
#include <sys/socket.h>
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
sockfd :套接字文件描述符,由socket()函数返回的。
serv_addr 是一个存储远程计算机的IP 地址和端口信息的结构。
addrlen 应该是sizeof(struct sockaddr)。
#include <sys/socket.h>
int listen(int sockfd, int backlog);
sockfd 是一个套接字描述符,由socket()系统调用获得。
backlog 是未经过处理的连接请求队列可以容纳的最大数目。
#include <sys/socket.h>
int accept(int sockfd, void *addr, int *addrlen);
sockfd 是正在listen() 的一个套接字描述符。
addr 一般是一个指向struct sockaddr_in 结构的指针;里面存储着远程连接过来的计算机的信息(比如远程计算机的IP 地址和端口)。
addrlen 是一个本地的整型数值,在它的地址传给accept() 前它的值应该是sizeof(struct sockaddr_in);accept()不会在addr 中存储多余addrlen bytes 大小的数据。如果accept()函数在addr 中存储的数据量不足addrlen,则accept()函数会改变addrlen 的值来反应这个情况。
#include <sys/types.h>
#include <sys/socket.h>
int send(int sockfd, const void *msg, int len, int flags);
sockfd 是代表你与远程程序连接的套接字描述符。
msg 是一个指针,指向你想发送的信息的地址。
len 是你想发送信息的长度。
flags 发送标记。一般都设为0(你可以查看send 的man pages来获得其他的参数值并且明白各个参数所代表的含义)。
#include <sys/types.h>
#include <sys/socket.h>
int recv(int sockfd, void *buf, int len, unsigned int flags);
sockfd 是你要读取数据的套接字描述符。
buf 是一个指针,指向你能存储数据的内存缓存区域。
len 是缓存区的最大尺寸。
flags 是recv() 函数的一个标志,一般都为0 (具体的其他数值和含义请参考recv()的man pages)。
#include <sys/types.h>
#include <sys/socket.h>
int sendto(int sockfd, const void *msg, int len, unsigned int flags,const struct sockaddr *to, int tolen);
sockfd 是代表你与远程程序连接的套接字描述符。
msg 是一个指针,指向你想发送的信息的地址。
len 是你想发送信息的长度。
flags 发送标记。一般都设为0。(你可以查看send 的man pages 来获得其他的参数值并且明白各个参数所代表的含义)
to 是一个指向struct sockaddr 结构的指针,里面包含了远程主机的IP 地址和端口数据。
tolen 只是指出了struct sockaddr 在内存中的大小sizeof(struct sockaddr)。
#include <sys/types.h>
#include <sys/socket.h>
int recvfrom(int sockfd, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen);
sockfd 是你要读取数据的套接字描述符。
buf 是一个指针,指向你能存储数据的内存缓存区域。
len 是缓存区的最大尺寸。
flags 是recv() 函数的一个标志,一般都为0 (具体的其他数值和含义请参考recv()的man pages)。
from 是一个本地指针,指向一个struct sockaddr 的结构(里面存有源IP 地址和端口数).
fromlen 是一个指向一个int 型数据的指针,它的大小应该是sizeof ( struct sockaddr).当函数返回的时候,formlen 指向的数据是form 指向的struct sockaddr 的实际大小.
#include <sys/socket.h>
int shutdown(int sockfd, int how);
sockfd 是一个你所想关闭的套接字描述符.
how 可以取下面的值。0 表示不允许以后数据的接收操;1 表示不允许以后数据的发送操作;2 表示和close()一样,不允许以后的任何操作(包括接收,发送数据)
shutdown() 如果执行成功将返回0,如果在调用过程中发生了错误,它将返回–1,全局变量errno 中存储了错误代码.
#include<sys/types.h>
#include<sys/socket.h>
int getsockopt(int sockfd, int level, int name, char *value, int *optlen);
int setsockopt(int sockfd, int level, int name, char *value, int *optlen);
sockfd 必须是一个已打开的套接字。
level 是函数所使用的协议标准(protocol level)(TCP/IP 协议使用IPPROTO_TCP,套接字标准的选项实用SOL_SOCKET)。
name 选项在套接字说明书中(man page)有详细说明。
value 指向为getsockopt()函数所获取的值,setsockopt()函数所设置的值的地址。
optlen 指针指向一个整数,该整数包含参数以字节计算的长度。
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);
sockfd 是你想取得远程信息的那个套接字描述符。
addr 是一个指向struct sockaddr (或是struct sockaddr_in)的指针。
addrlen 是一个指向int 的指针,应该赋于sizeof(struct sockaddr)的大小。