概要
Udp协议为非面向连接的协议,数据的发送与接收并不需要像TCP/IP协议那样事先建立连接,因此在数据发送速度及资源消耗表现上都胜于TCP/IP;但UDP为非可靠协议其发送(接收)数据并不一定能够保证对方能够正确的接收(发送),其可靠性需要另外的机制来实现。
发送端的实现用到的几个函数
1. WSAStartup:启动Winsocket
2. socket:创建Socket,参数指定为SOCK_DGRAM 接收包数据
3. bind:设置用于接收数据的端口和地址
4. recvfrom:从socket中接收数据
5. closesocket:关闭socket
6. WSACleanup:关闭Winsocket
与TCP/IP相比不需要调用的函数:
Udp协议为非面向连接的协议,数据的发送与接收并不需要像TCP/IP协议那样事先建立连接,因此在数据发送速度及资源消耗表现上都胜于TCP/IP;但UDP为非可靠协议其发送(接收)数据并不一定能够保证对方能够正确的接收(发送),其可靠性需要另外的机制来实现。
发送端的实现用到的几个函数
1. WSAStartup:启动Winsocket
2. socket:创建Socket,参数指定为SOCK_DGRAM 接收包数据
3. bind:设置用于接收数据的端口和地址
4. recvfrom:从socket中接收数据
5. closesocket:关闭socket
6. WSACleanup:关闭Winsocket
与TCP/IP相比不需要调用的函数:
- listen :监听socket
- accept :接收客户端的请求
- 接收和发送的函数不一样tcp为 send/recv; udp为sendto/recvfrom
建立UDP服务端(接收端),它接收30次数据;接收包数据的最大长度为4096,超过此长度将会发生截断。
服务端:
#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsd; //初始化信息
SOCKET soRecv; //接收SOCKET
char * pszRecv = NULL; //接收数据的数据缓冲区指针
int nRet = 0;
int i = 0;
int dwSendSize = 0;
SOCKADDR_IN siRemote,siLocal; //远程发送机地址和本机接收机地址
//启动Winsock
if (WSAStartup(MAKEWORD(2,2),&wsd) != 0) {
cout << "WSAStartup Error = " << WSAGetLastError() << endl;
return 0;
}
//创建socket
soRecv = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (soRecv == SOCKET_ERROR) {
cout << "socket Error = " << WSAGetLastError() << endl;
return 1;
}
//设置端口号
int nPort = 5150;
//int nPort = 1234;
siLocal.sin_family = AF_INET;
siLocal.sin_port = htons(nPort);
siLocal.sin_addr.s_addr = inet_addr("127.0.0.1");
//绑定本地地址到socket
if (bind(soRecv,(SOCKADDR*)&siLocal,sizeof(siLocal)) == SOCKET_ERROR) {
cout << "bind Error = " << WSAGetLastError() << endl;
return 1;
}
//申请内存
pszRecv = new char[4096];
if (pszRecv == NULL) {
cout << "pszRecv new char Error " << endl;
return 0;
}
for (int i = 0; i < 30; i ++){
dwSendSize = sizeof(siRemote);
//开始接受数据
nRet = recvfrom(soRecv,pszRecv,4096,0,(SOCKADDR*)&siRemote,&dwSendSize);
if (nRet == SOCKET_ERROR) {
cout << "recvfrom Error " << WSAGetLastError() << endl;
break;
}
else if (nRet == 0) {
break;
}
else{
pszRecv[nRet] = '\0';
cout << inet_ntoa(siRemote.sin_addr) << endl
<<pszRecv << endl;
}
}
//关闭socket连接
closesocket(soRecv);
delete[] pszRecv;
//清理
WSACleanup();
system("pause");
return 0;
}
客户端:
#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsd; //初始化信息
SOCKET soSend; //接收SOCKET
int nRet = 0;
int i = 0;
int dwSendSize = 0;
SOCKADDR_IN siLocal; //远程发送机地址和本机接收机地址
//启动Winsock
if (WSAStartup(MAKEWORD(2,2),&wsd) != 0) {
cout << "WSAStartup Error = " << WSAGetLastError() << endl;
return 0;
}
//创建socket
soSend = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (soSend == SOCKET_ERROR) {
cout << "socket Error = " << WSAGetLastError() << endl;
return 1;
}
//设置端口号
int nPort = 5150;
siLocal.sin_family = AF_INET;
siLocal.sin_port = htons(nPort);
siLocal.sin_addr.s_addr = inet_addr("127.0.0.1");
for (int i = 0; i < 30; i ++){
//开始接受数据
nRet = sendto(soSend,"123 mutouren",strlen("123 mutouren"),0,(SOCKADDR*)&siLocal,sizeof(SOCKADDR));
if (nRet == SOCKET_ERROR) {
cout << "sendto Error " << WSAGetLastError() << endl;
break;
}
}
//关闭socket连接
closesocket(soSend);
//清理
WSACleanup();
return 0;
}