设计模型
服务器和客户端启动没有顺序之分(因为不需要三次握手,这也是与TCP的区别)
客户端启动就直接发数据
服务端启动就直接接数据
UDP基本函数使用简化图
代码如下:
LocalUDPServer.cpp
#include <tchar.h> // _T宏
#include <stdio.h>// printf sprintf
#include <iostream>// cout fstream
using namespace std;
// windows socket
#include <winsock.h>
#pragma comment (lib,"ws2_32.lib")
bool initSocketLib();
void main()
{
if(!initSocketLib())
return;
// 初始化本地客户端套接字
SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(serSocket == INVALID_SOCKET)
{
printf("socket error !");
return ;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(514);
serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1")/*INADDR_ANY*/;
if(bind(serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("bind error !");
closesocket(serSocket);
return ;
}
sockaddr_in remoteAddr;
int nAddrLen = sizeof(remoteAddr);
while (true)
{
char recvData[255];
int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen);
if (ret > 0)
{
recvData[ret] = 0x00;
printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
printf(recvData);
}
//char * sendData = "一个来自服务端的UDP数据包\n";
//sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)&remoteAddr, nAddrLen);
}
closesocket(serSocket);
WSACleanup();
return;
}
bool initSocketLib()
{
WSADATA Data;
//初始化windows Socket Dll
int status = WSAStartup(MAKEWORD(1,1),&Data);
if (0!=status)
{
printf(_T("初始化失败\n"));
return false;
}
return true;
}
RemoteUDPServer.cpp
#include <tchar.h> // _T宏
#include <stdio.h>// printf sprintf
#include <iostream>// cout fstream
using namespace std;
// windows socket
#include <winsock.h>
#pragma comment (lib,"ws2_32.lib")
bool initSocketLib();
void main()
{
if(!initSocketLib())
return;
// 初始化本地客户端套接字
SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(serSocket == INVALID_SOCKET)
{
printf("socket error !");
return ;
}
// "本地"的服务端地址映射(IP:port)
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(514);
serAddr.sin_addr.S_un.S_addr = inet_addr("192.168.0.53");// 因为这是远程机器,客户端也不在本机上,所以绑定实际的物理地址
if(bind(serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("bind error !");
closesocket(serSocket);
return ;
}
sockaddr_in remoteAddr;
int nAddrLen = sizeof(remoteAddr);
while (true)
{
char recvData[255];
int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen);
if (ret > 0)
{
recvData[ret] = 0x00;
printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
printf(recvData);
}
//char * sendData = "一个来自服务端的UDP数据包\n";
//sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)&remoteAddr, nAddrLen);
}
closesocket(serSocket);
WSACleanup();
return ;
}
bool initSocketLib()
{
WSADATA Data;
//初始化windows Socket Dll
int status = WSAStartup(MAKEWORD(1,1),&Data);
if (0!=status)
{
printf(_T("初始化失败\n"));
return false;
}
return true;
}
LocalUDPClient.cpp
#include <tchar.h> // _T宏
#include <stdio.h>// printf sprintf
#include <iostream>// cout fstream
using namespace std;
// windows socket
#include <winsock.h>
#pragma comment (lib,"ws2_32.lib")
bool initSocketLib();
void main()
{
if(!initSocketLib())
return;
// 初始化本地客户端套接字
SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sclient == INVALID_SOCKET)
{
printf("socket error !");
return;
}
// 本地的服务端地址映射(IP:port)
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(514);
sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int len = sizeof(sin);
// 远程的服务端地址映射(IP:port)
sockaddr_in sinEx;
sinEx.sin_family = AF_INET;
sinEx.sin_port = htons(514);
sinEx.sin_addr.S_un.S_addr = inet_addr("192.168.0.53");
int lenEx = sizeof(sinEx);
char sendData[512];
UINT iCount = 0;
while (true)
{
memset(sendData,0,512);
sprintf(sendData,"client Send %3d\n",iCount++);
int senRet = sendto(sclient, sendData, strlen(sendData), 0, (sockaddr *)&sin, len);
if(senRet == SOCKET_ERROR ){
printf("send is error");
}
senRet = sendto(sclient, sendData, strlen(sendData), 0, (sockaddr *)&sinEx, lenEx);
if(senRet == SOCKET_ERROR ){
printf("send is error");
}
printf(sendData);
/* 这段注释的代码可以加上,为了理解UDP编程没必要
char recvData[255];
int ret = recvfrom(sclient, recvData, 255, 0, (sockaddr *)&sin, &len);
if(ret > 0)
{
recvData[ret] = 0x00;
printf(recvData);
}
*/
Sleep(1000);// 发的太快也没啥意思
}
closesocket(sclient);
WSACleanup();
return;
}
bool initSocketLib()
{
WSADATA Data;
//初始化windows Socket Dll
int status = WSAStartup(MAKEWORD(1,1),&Data);
if (0!=status)
{
printf(_T("初始化失败\n"));
return false;
}
return true;
}