网络协议栈Socket编程.pptx
课程内容Socket编程概述1Socket函数2TCP Socket编程3UDP Socket编程4第1页/共47页Socket编程概述第2页/共47页IPv4 Socket地址结构struct in_addr in_addr_t s_addr;/*32-bit IPv4 address*/*network byte ordered*/;uint32_t第3页/共47页IPv4 Socket地址结构struct sockaddr_in uint8_t sin_len;sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;char sin_zero8;length of structure(16)AF_INET16-bit TCP or UDP port numbernetwork byte ordered 32-bit IPv4 address network byte ordered uint16_tunused第4页/共47页Socket通用地址结构struct sockaddrsockaddr uint8_t sa_len;sa_family_t sa_family;char sa_data14;address family:AF_XXX valueprotocol-specific address length of structure(16)第5页/共47页字节序字节在内存中存储或在网络中传输的顺序;例如一个2字节的short型整数AB,A和B各代表一个字节;存储方式有两种:ABABn+1 nn+1 n“little-endian“和“big-endian”指示一个多字节值的哪一端存储在起始位置上。little endianbig endian第6页/共47页字节序不同的CPU架构采用不同的字节序X86 little-endianPowerPC big-endianSparcbig-endianIP协议数据包结构使用big-endian第7页/共47页字节序需要协调主机使用的字节序和网络使用字节序;第8页/共47页字节序htonshtonlntohsntohl第9页/共47页字节序#include uint16_t htons(uint16_t host16bitvalue);uint32_t htonl(uint32_t host32bitvalue);uint16_t ntohs(uint16_t net16bitvalue);uint32_t ntohl(uint32_t net32bitvalue);Both return:value in network byte order Both return:value in host byte order第10页/共47页socket套接口的建立【参数】family:协议族 AF_INET#include int socket(int family,int type,int protocol);第11页/共47页socket【参数】(续)type:套接口的类型SOCK_STREAM 提供TCP套接字SOCK_DAGRAM 提供UDP套接字protocol:指示对套接字应使用哪个协议。通常设置为0【返回值】如果调用成功,返回套接字句柄,否则返回-1。第12页/共47页socket【示例】int tcpSock=socket(AF_INET,SOCK_STREAM,0)int udpSock=socket(AF_INET,SOCK_DGRAM,0)第13页/共47页bind为socket分配本地协议地址。【参数】sockfd:套接字描述符;address:存储IP地址和端口号的数据结构;addrlen:address参数的长度。#include int bind(int sockfd,const struct sockaddr*address,socklen_t addrlen);第14页/共47页bind【返回值】正确调用返回0,否则返回-1。【示例】struct sockaddr_in serverAddr;serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(3000);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);bind(tcpSock,(struct sockaddr*)&serverAddr,sizeof(serverAddr);第15页/共47页listen建立套接口队列【参数】sockfd:套接口描述符;backlog:socket队列的最大连接数。【返回值】正确调用返回0,否则返回-1。#include#int listen(int sockfd,int backlog);第16页/共47页accept等待连接请求。【参数】cliaddr:存放客户端协议地址结构,如果对其不感兴趣,可以设为NULL;addrlen:cliaddr的长度。#include int accept(int sockfd,struct sockaddr*cliaddr,socklen_t*addrlen);第17页/共47页accept【返回值】返回新建的套接口描述。第18页/共47页connect连接服务器【参数】servaddr:要连接的服务器端协议地址结构;addrlen:servaddr的长度。#include int connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen);第19页/共47页connect【返回值】成功调用返回0,否则返回-1。【示例】serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(3000);serverAddr.sin_addr.s_addr=inet_addr(1.2.3.4);connect(tcpSock,(struct sockaddr*)&serverAddr,sizeof(serverAddr);第20页/共47页recv/sendTCP接收/发送函数【参数】buf:缓存区首地址。len:期望接收/发送的字节数。int recv(int socket,void*buf,size_t len,int flag);int send(int socket,const void*buf,size_t len,int flags)第21页/共47页recv/send【返回值】成功调用返回实际接收/发送字节数,否则返回-1。参数说明flags:通信参数,一般设置为0。【示例】send(tcpSock,Hello,6,0);char buffer100;recv(tcpSock,buffer,100,0);第22页/共47页recvfrom/sendtoUDP接收/发送函数【参数】from/to:指向通信对端协议地址;fromlen/tolen:地址参数的长度;int recvfrom(int socket,void*buf,size_t len,int flag,struct sockaddr*from,int*fromlen);int sendto(int socket,const void*buf,size_t len,int flags,const struct sockaddr*to,int tolen)第23页/共47页recvfrom/sendto【返回值】成功调用返回实际接收/发送字节数,否则返回-1。【示例】serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(3000);serverAddr.sin_addr.s_addr=inet_addr(1.2.3.4);sendto(udpSock,Hello,6,0,(struct sockaddr*)&serverAddr,sizeof(serverAddr);char buffer100;recvfrom(udpSock,buffer,100,0,(struct sockaddr*)&serverAddr,sizeof(serverAddr);第24页/共47页close关闭套接口int close(intint close(int sockfd););第25页/共47页 TCP 编程第26页/共47页SocketHeader.h#include#include#include#include void print_error(char*error_info)printf(%s failedn,error_info);exit(-1);第27页/共47页TCPServer.c#include SocketHeader.h“int main(void)struct sockaddr_in local;int tcpSock;int tcpSockNew;int result;char buffer100;int recvSize=0;local.sin_family=AF_INET;local.sin_port=htons(3000);local.sin_addr.s_addr=inet_addr(1.2.3.4);初始化本地协议地址结构第28页/共47页TCPServer.c tcpSock=socket(AF_INET,SOCK_STREAM,0);if(tcpSock 0)print_error(socket);result=bind(tcpSock,(struct sockaddr*)&local,sizeof(local);if(result 0)close(tcpSock);print_error(bind);创建套接口为创建的套接口分配协议地址第29页/共47页TCPServer.c result=listen(tcpSock,5);if(result 0)close(tcpSock);print_error(listen);tcpSockNew=accept(tcpSock,NULL,NULL);if(tcpSockNew 0)close(tcpSock);print_error(accept);为套接口创建等待队列等待连接请求第30页/共47页TCPServer.c recvSize=recv(tcpSockNew,buffer,100,0);if(recvSize 0)close(tcpSockNew);close(tcpSock);print_error(recv);result=send(tcpSockNew,buffer,recvSize,0);if(result 0)close(tcpSockNew);close(tcpSock);print_error(send);从客户端接收数据将数据发送给客户端第31页/共47页TCPServer.c close(tcpSockNew);close(tcpSock);return 0;第32页/共47页TCPClient.c#include SocketHeader.hint main(void)struct sockaddr_in servAddr;int tcpSock;int result;char buffer100;int recvSize=0;servAddr.sin_family=AF_INET;servAddr.sin_port=htons(3000);servAddr.sin_addr.s_addr=inet_addr(1.2.3.4);初始化服务器端协议地址结构第33页/共47页TCPClient.c tcpSock=socket(AF_INET,SOCK_STREAM,0);if(tcpSock 0)print_error(socket);result=connect(tcpSock,(struct sockaddr*)&servAddr,sizeof(servAddr);if(result 0)close(tcpSock);print_error(connect);创建套接口连接服务器第34页/共47页TCPClient.c result=send(tcpSock,Hello,6,0);if(result 0)close(tcpSock);print_error(send);recvSize=recv(tcpSock,buffer,100,0);if(recvSize 0)close(tcpSock);print_error(recv);发送数据给服务器从服务器端接收数据第35页/共47页TCPClient.c printf(%sn,buffer)close(tcpSock);return 0;第36页/共47页UDP编程第37页/共47页UDPServer.c#include SocketHeader.hint main(void)struct sockaddr_in local;struct sockaddr_in client;int clientSize;int udpSock;int result;char buffer100;int recvSize=0;local.sin_family=AF_INET;local.sin_port=htons(3000);local.sin_addr.s_addr=INADDR_ANY;初始化服务器端协议地址结构第38页/共47页UDPServer.c udpSock=socket(AF_INET,SOCK_DGRAM,0);if(udpSock 0)print_error(socket);result=bind(udpSock,(struct sockaddr*)&local,sizeof(local);if(result 0)close(udpSock);print_error(bind);创建套接口为创建的套接口分配协议地址第39页/共47页UDPServer.c clientSize=sizeof(client);recvSize=recvfrom(udpSock,buffer,100,0,(struct sockaddr*)&client,&clientSize);if(recvSize 0)close(udpSock);print_error(recvfrom);result=sendto(udpSock,buffer,recvSize,0,(struct sockaddr*)&client,clientSize);if(result 0)close(udpSock);print_error(sendto);从客户端接收数据将数据发送给客户端第40页/共47页UDPServer.c close(udpSock);return 0;第41页/共47页UDPClient.c#include SocketHeader.hint main(void)struct sockaddr_in local;struct sockaddr_in server;int serverSize;int udpSock;int result;char buffer100;local.sin_family=AF_INET;local.sin_port=htons(0);local.sin_addr.s_addr=NADDR_ANY;初始化本地协议地址结构第42页/共47页UDPClient.c udpSock=socket(AF_INET,SOCK_DGRAM,0);if(udpSock 0)print_error(socket);result=bind(udpSock,(struct sockaddr*)&local,sizeof(local);if(result 0)close(udpSock);print_error(bind);创建套接口为创建的套接口分配协议地址第43页/共47页UDPClient.c serverSize=sizeof(server);server.sin_family=AF_INET;server.sin_port=htons(3000);server.sin_addr.s_addr=inet_addr(1.2.3.4);result=sendto(udpSock,buffer,100,0,(struct sockaddr*)&server,serverSize);if(result 0)close(udpSock);print_error(sendto);初始化服务器端协议地址结构发送数据给服务器端第44页/共47页UDPClient.c result=recvfrom(udpSock,buffer,100,0,(struct sockaddr*)&server,&server Size);if(result 0)close(udpSock);print_error(recvfrom);printf(%sn,buffer);close(udpSock);return 0;从服务器端接收数据第45页/共47页谢谢谢谢第46页/共47页感谢您的观看!第47页/共47页