1.创建套接字
int socket( int domain, int type, int protocol);
>domain是地址族
PF_INET //internel 协议
PF_UNIT //unit internal 协议
PF_NS //Xerox NS协议
PF_IMPLINK //interface Message
>type 套接字类型
SOCK_STREAM //流式套接字
SOCK_DGRAM //数据报套接字
SOCK_RAW //原始套接字
>protocol 参数通常置为0,当type 是SOCK_RAM时才会用到
>函数返回值:
成功:返回套接字描述符
失败:返回 -1
2.绑定地址bind()
>int bind(int sockfd, struct sockaddr *my_addr, int addlen);
>sockfd: socket 返回的文件描述符
>addrlen: sockaddr 地址结构的长度
>返回值:0 或 -1
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
通用地址结构
>struct sockaddr
{
u_short as_family; //地址族
char sa_data[14]; //14字节协议地址
}
>Internel协议地址结构
struct sockaddr_in
{
u_short sin_family; //地址族,
u_short sin_port; //端口
struct in_addr sin_addr; //IPV4地址
char sin_zero[8]; //作为对齐用
}
>IPV4地址结构
struct in_addr
{
in_addr s_addr;
}
>地址结构的一般用法
1. 定义一个struct sockaddr_in 类型的变量并清空
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
2. 填充地址信息
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(9999);//要大于5000 小于65536
myaddr.sin_addr.s_addr = inet_addr("192.168.1.100");
3. 将该变量强制转换为struct sockaddr类型在函数中使用bind(listenfd, (struct sockaddr *)(&myaddr), sizeof(myaddr));
>地址转换函数
>unsigned long inet_addr(char *address);
address 是以NULL结尾的点分IPV4字符串。该函数返回32位的地址。如果字符串包含的不是合法的IP地址,则函数返回 -1.
例如:
struct in_addr addr;
addr.s_addr = inet_addr("192.168.1.100");
>char *inet_ntoa(struct in_addr address);
address 是IPV4地址结构,函数返回一指向包含点分IP地址的静态存储字符指针。如果错误则函数返回NULL
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.>>>>>>>>>>>>>>>
3. listen
>int listen ( int sockfd, int backlog)
>sockfd, :监听连接的套接字
>backlog:
指定等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求
DoS(拒接服务)攻击即利用了这个原理,非法的连接占用了全部的连接数,造成正常的连接请求被拒绝。
>返回值:0或 -1
4.accept() //服务端使用的系统调用
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
>返回值:已建立好连接的套接字或 -1
>sockfd:监听套接字
>addr : 对方地址
>addrlen:地址长度
5. connect()//connect 是客户端使用的系统调用
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
函数参数:
sockfd: socket返回的文件描述符
serv_addr:服务器端的地址信息
addrlen: serv_addr的长度
返回值:
0或-1
5.send()
ssize_t send(int socket, const void *buffer, size_t length, int flags);
函数参数
buffer: 发送缓冲区首地址
length:发送的字节数
flags:发送方式(通常为0)
返回值:
>成功:实际发送的字节数
>失败:-1,并设置errno
6.recv()
ssize_t recv(int socket, const void *buffer, size_t length, int flags);
函数参数
buffer:发送缓冲区的首地址
length:发送的字节数
flags:接受方式(通常为0)(超时接收会用到这个参数)
返回值:
>成功:实际接收的字节数
>失败:-1,并设置error
注:
send()和recv()可以用write和read代替
7.sendto()和recvfrom()
ssize_t sendto(int socket, void *message, size_t length, int flags, struct sockaddr *dest_addr, socklen_t dest_len);
ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len );
这两个函数一般在使用UDP协议时使用
TCP服务器端流程
TCP客户端流程