Socket:Socket被称做 套接字,是网络通信中的一种约定。
Socket编程的应用无处不在,我们平时用的QQ、微信、浏览器等程序.都与Socket编程有关。
三次握手 四次断开
面试可能会问:
为什么建立连接只需要三次数据交互,而断开连接需要四次呢?
建立连接时,服务端在监听状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
UDP协议:用户数据报协议。是一种无连接的传输层协议,提供面向事务的简单不可靠传送服务,
可以保证通讯效率,传输延时小。
socket编程的API接口:
1.(1)创建套接字socket:socket()函数
int socket(int af,int type,int protocol);
//af:地址族 type数据传输方式:
面向连接(SOCK_STREAM)即TCP
无连接(SOCK_DGRAM)即UDP
//创建TCP套接字
int tcp_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//创建UDP套接字
int udp_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
(2)绑定套接字:bind()函数
int bind(int sock,struct sockaddr *addr,socklen_t addrlen);
/*
sock为socket文件描述符;addr为sockaddr结构体变量的指针;
addrlen为addr变量的大小,可由sizeof()计算得出
*/
//使用示例:
//将创建的套接字 ServerSock与本地IP 127.0.0.1 端口1413进行绑定
/*创建服务端socket*/
int ServerSock = socket(PF_INET,SOCK_STREAM,IPPORTO_TCP);
/*设置服务端信息*/
struct sockaddr_in ServerSockAddr;
memset(&ServerSockAddr,0,sizeof(ServerSockAddr)); //给结构体ServerSockAddr 清零
ServerSockAddr.sin_family = PF_INET; //使用IPV4地址
ServerSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //本机ip地址
ServerSockAddr.sin_port = htons(1413); //端口号
/*绑定套接字*/
bind(ServerSock,(SOCKADDR*)&ServerSockAddr,sizeof(SOCKADDR));
/*
其中 struct sockaddr_in 类型的结构体变量 用于保存IPv4的IP信息。
若是IPv6,则有对应的结构体,如:
*/
struct sockaddr_in6{
sa_family_t sin6_family; //地址类型,取值为AF_INET6
in_port_t sin6_port; //16位端口号
uint32_t sin6_flowinfo; //IPV6流信息
uint32_t sin6_scope_id; //接口范围id
};
(3)建立连接:connect()函数
函数原型:
int connect(int sock,struct sockaddr *serv_addr,socklen_t addrlen);
示例:
int ClientSock = socket(AF_INET,SOCK_STREAM,IPPORTO_TCP);
connect(ClientSock,(SOCKADDR*)&ServerSockAddr,sizeof(SOCKADDR));
(4)监听:listen()函数
函数原型:
int listen(int sock,int backlog);
//sock为需要进入监听状态的套接字;backlog为请求队列的最大长度
示例:/*进入监听状态*/
listen(ServerSock,10);
(5)接收请求:accepet()函数
函数原型:
int accpet(int sock,struct sockaddr *addr,socklen_t *addrlen);
/*
sock 为服务器端套接字。
addr 为 sockaddr_in 结构体变量。
addrlen 为参数 addr 的长度,可由 sizeof() 求得。
*/
示例:/*监听客户端请求,accept函数返回一个新的套接字,发送和接收都是用这个套接字*/
int ClientSock = accept(ServerSock,(SOCKADDR*)&ClientAddr,&len);
(6)关闭:close()函数
函数原型:
int close(int fd);//fd 要关闭的文件描述符
示例:
Close(ServerSock);
(7)数据的接收和发送
数据收发函数有几组:
read()/write()
recv()/send()
readv()/writev()
recvmsg()/sendmsg()
recvfrom()/sendto()
函数原型:
ssize_t read(int fd,void *buf,size_t count);
ssize_t write(int fd,const void *buf,size_t count);
ssize_t send(int sockfd,const void *buf,size_t len,int flags);
ssize_t recv(int sockfd,void *buf,size_t len,int flags);
ssize_t sendto(int sockfd,const void *buf, size_t len,int flags,const struct sockaddr *dest_addr,socklen_taddrlen);
ssize_t recvfrom(int sockfd, void *buf,
size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen);
ssize_t sendmsg(int sockfd,const struct msghdr *msg,int flags);
ssize_t recvmsg(int sockfd,struct msghdr *msg,int flags);
@资料来源 嵌入式大杂烩