udp 学习

来源:互联网 发布:ubuntu翻译软件 编辑:程序博客网 时间:2024/06/06 12:59

/****************************************************************

* 什么是socket机制?

****************************************************************/


TCP 有连接的信息传输方式;

UPD 协议是无连接的,并不保证每个数据包都会到达目的地,也不保证到达的顺序;

UDP数据包有大小,最大限制是IP数据包大小的最大限制:65507byte.


设计UDP server类和IUDP client类

class UDPServerSock: public BaseSock {private:sockaddr_in serverSockAddr;protected:mutable sockaddr_in lastfromSockAddr;sockaddr_in destinationSockAddr;char* preBuffer;int preBufferSize;mutable int preReceivedLength;public:explicit UDPServerSock(unsigned short server_port,int pre_buffer_size = 32);virtual ~UDPServerSock();void UDPSetDest(const char* dest_IP,const unsigned short& dest_port);void UDPSetDest(const sockaddr_in& dest_sock_addr);int UDPReceive() const;int UDPSendtoDest(const char* send_data,const int& data_length) const;};/* 我们把最后一次来向地址以及预接收缓存中的收到的数据长度设置成mutable 是因为我们希*  望接收UDPReceive()这个方法看起来是不改变对象的。每一次接收,实际上都会刷新*  lastfromSockAddr , 而作为服务器, 往往也是通过lastfromSockAddr 去决定*  destinationSockAddr 的。*/UDPServerSock::UDPServerSock(unsigned short server_port,int pre_buffer_size):preBufferSize(pre_buffer_size), preReceivedLength(0) {preBuffer = new char[preBufferSize];memset(&serverSockAddr, 0, sizeof(serverSockAddr));memset(&lastfromSockAddr, 0, sizeof(lastfromSockAddr));memset(&destinationSockAddr, 0, sizeof(destinationSockAddr));serverSockAddr.sin_family = AF_INET;serverSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverSockAddr.sin_port = htons(server_port);sockFD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sockFD < 0) {sockClass::error_info("sock() failed.");}if (bind( sockFD,(sockaddr*)&serverSockAddr,sizeof(serverSockAddr)) < 0) {sockClass::error_info("bind() failed.");}}UDPServerSock::~UDPServerSock(){delete [] preBuffer;close(sockFD);}/* 构造函数依然使用socket()建立sockFD,然后通过bind()将本机的SockAddr(主要是指定了* 端口)绑定到这个sockFD 上。* 我们重载了UDPSetDest() 这个方法, 可以有两种方式去指定目标地址* destinationSockAddr——既可以指定IP 地址和端口,也可以直接赋值以sockaddr_in 结构。*/void UDPServerSock::UDPSetDest(const char* dest_IP,const unsigned short& dest_port) {destinationSockAddr.sin_family = AF_INET;destinationSockAddr.sin_addr.s_addr = inet_addr(dest_IP);destinationSockAddr.sin_port = htons(dest_port);}void UDPServerSock::UDPSetDest(const sockaddr_in& dest_sock_addr){destinationSockAddr.sin_family = dest_sock_addr.sin_family;destinationSockAddr.sin_addr.s_addr = dest_sock_addr.sin_addr.s_addr;destinationSockAddr.sin_port = dest_sock_addr.sin_port;}/* 最后是接收和发送。我们知道TCP 里面recv()返回0 表示连接正常断开,而UDP 里面,则*  仅仅就是表示收到0 字节的数据包。可见,数据大小为0,并不代表数据包为空,因为这个*  数据包实际也是一个数据报,包含着TCP 数据报的各种必要信息。*/int UDPServerSock::UDPReceive() const{socklen_t from_add_len = sizeof(lastfromSockAddr); //use int in win32preReceivedLength = recvfrom( sockFD,preBuffer,preBufferSize,0,(sockaddr*)&lastfromSockAddr,&from_add_len);if ( preReceivedLength < 0) {sockClass::error_info("recv() failed.");}return preReceivedLength;}int UDPServerSock::UDPSendtoDest(const char* send_data,const int& data_length) const{int send_message_size = sendto( sockFD,send_data,data_length,0,(sockaddr*)&destinationSockAddr,sizeof(destinationSockAddr));if (send_message_size < 0) {sockClass::error_info("send() failed.");}if (send_message_size != data_length) {sockClass::error_info("send() sent a different number of bytes than expected.");}return send_message_size;}
UDPclient
class UDPClientSock: public BaseSock {protected:mutable sockaddr_in lastfromSockAddr;sockaddr_in destinationSockAddr;char* preBuffer;int preBufferSize;mutable int preReceivedLength;public:explicit UDPClientSock(int pre_buffer_size = 32);virtual ~UDPClientSock();void UDPSetDest(const char* dest_IP,const unsigned short& dest_port);void UDPSetDest(const sockaddr_in& dest_sock_addr);int UDPReceive() const;int UDPSendtoDest(const char* send_data,const int& data_length) const;};UDPClientSock::UDPClientSock(int pre_buffer_size):preBufferSize(pre_buffer_size), preReceivedLength(0){preBuffer = new char[preBufferSize];memset(&lastfromSockAddr, 0, sizeof(lastfromSockAddr));memset(&destinationSockAddr, 0, sizeof(destinationSockAddr));sockFD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sockFD < 0) {sockClass::error_info("sock() failed.");}}UDPClientSock::~UDPClientSock(){delete [] preBuffer;close(sockFD);}// 其它4 个类方法,跟server 端的简直一模一样。void UDPClientSock::UDPSetDest(const char* dest_IP, const unsigned short& dest_port) {destinationSockAddr.sin_family = AF_INET;destinationSockAddr.sin_addr.s_addr = inet_addr(dest_IP);destinationSockAddr.sin_port = htons(dest_port);}void UDPClientSock::UDPSetDest(const sockaddr_in& dest_sock_addr) {destinationSockAddr.sin_family = dest_sock_addr.sin_family;destinationSockAddr.sin_addr.s_addr = dest_sock_addr.sin_addr.s_addr;destinationSockAddr.sin_port = dest_sock_addr.sin_port;}int UDPClientSock::UDPReceive() const {socklen_t from_add_len = sizeof(lastfromSockAddr); //use int in win32preReceivedLength = recvfrom( sockFD, preBuffer, preBufferSize, 0, (sockaddr*)&lastfromSockAddr, &from_add_len);if ( preReceivedLength < 0) {sockClass::error_info("recv() failed.");}return preReceivedLength;}int UDPClientSock::UDPSendtoDest(const char* send_data, const int& data_length) const {int send_message_size = sendto( sockFD,send_data,data_length,0,(sockaddr*)&destinationSockAddr,sizeof(destinationSockAddr));if (send_message_size < 0) {sockClass::error_info("send() failed.");}if (send_message_size != data_length) {sockClass::error_info("send() sent a different number of bytes than expected.");}return send_message_size;}

0 0
原创粉丝点击