//#pragma once
//UDP协议
//https://blog.csdn.net/xxbsky520/article/details/6161217
#include <winsock2.h>
#pragma comment(lib, "WS2_32")//https://www.cnblogs.com/wyj553/archive/2009/04/16/1437512.html
#include <iostream>
using namespace std;
int main()
{
SOCKET sock; //socket套接字
char szMsg[] = "this is a UDP test package";//被发送的字段
//1.启动SOCKET库,版本为2.0
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (0 != err) //检查Socket初始化是否成功
{
cout << "Socket2.0初始化失败,Exit!";
return 0;
}
//检查Socket库的版本是否为2.0
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
{
WSACleanup();
return 0;
}
//2.创建socket,
sock = socket(
AF_INET, //internetwork: UDP, TCP, etc
SOCK_DGRAM, //SOCK_DGRAM说明是UDP类型
0 //protocol
);
if (INVALID_SOCKET == sock) {
cout << "Socket 创建失败,Exit!";
return 0;
}
//3.设置该套接字为广播类型,
bool opt = true;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char FAR *>(&opt), sizeof(opt));
//4.设置发往的地址
sockaddr_in addrto; //发往的地址
memset(&addrto, 0, sizeof(addrto));
addrto.sin_family = AF_INET; //地址类型为internetwork
addrto.sin_addr.s_addr = INADDR_BROADCAST; //设置ip为广播地址
addrto.sin_port = htons(7861); //端口号为7861
int nlen = sizeof(addrto);
unsigned int uIndex = 1;
while (uIndex < 10)//true
{
Sleep(1000); //程序休眠一秒
//向广播地址发送消息
/*7.12 sendto函数
在Socket中有两套发送和接收函数,一是sendto和recvfrom;二是send和recv。前一套在函数参数中要指明地址;而后一套需要先将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。
sendto的定义如下:
int PASCAL FAR sendto(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR *to, int tolen);
第一个参数就是套接字;
第二个参数是要传送的数据指针;
第三个参数是要传送的数据长度(字节数);
第四个参数是传送方式的标识,如果不需要特殊要求则可以设置为0,其它值请参考MSDN;
第五个参数是目标地址,注意这里使用的是sockaddr的指针;
第六个参数是地址的长度;
返回值为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。*/
if (sendto(sock, szMsg, strlen(szMsg), 0, (sockaddr*)&addrto, nlen)
== SOCKET_ERROR)
cout << WSAGetLastError() << endl;
else
cout << uIndex++ << ":an UDP package is sended." << endl;
}
if (!closesocket(sock)) //关闭套接字
{
WSAGetLastError();
return 0;
}
if (!WSACleanup()) //关闭Socket库
{
WSAGetLastError();
return 0;
}
return 0;
}
VS2017下成功运行
参考:
https://blog.csdn.net/xxbsky520/article/details/6161217
https://www.cnblogs.com/wyj553/archive/2009/04/16/1437512.html
下面是完整例子
服务端:
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "WS2_32")
using namespace std;
int main()
{
//1.启动SOCKET库,版本为2.0
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
cout << "Socket2.0初始化失败,Exit!";
return 0;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
{
WSACleanup();
return 0;
}
//2.创建套接字
SOCKET sock;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
cout << "Socket 创建失败,Exit!";
return 0;
}
//3.绑定
SOCKADDR_IN myaddr; //sockaddr_in相当于sockaddr结构
memset(&myaddr, 0, sizeof(myaddr));//初始化 清零
myaddr.sin_family = AF_INET;//只能为这个值
//如果绑定地址不是本机地址或者ADDR_ANY,则recvfrom函数不会正确接收,而是立刻返回
myaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//将u_long型转换为网络字节序列
//端口号必须和客户发往的端口号一致
myaddr.sin_port = htons(7861);//将u_short型转换为网络字节序列
bind(sock, (SOCKADDR*)&myaddr, sizeof(myaddr));//绑定套接字
//4.等待并接受数据
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
char buf[256] = "";
long number = 0;
while (true) {
Sleep(1000);
number++;
//recv(sock, buf, sizeof(buf), 0);
recvfrom(sock, buf,256,0,(SOCKADDR*)&addrClient, &len);
cout << number << ":" << buf << endl;
memset(buf, 0, sizeof(buf));
if (number > 5)break;
}
//??这两个条件?
//if (!closesocket(sock))
//{
// WSAGetLastError();
// return 0;
//}
//if (!WSACleanup())
//{
// WSAGetLastError();
// return 0;
//}
cout << "服务器关闭" << endl;
closesocket(sock);
WSACleanup();
return 0;
}
客户端:
#include <winsock2.h>
#pragma comment(lib, "WS2_32")
#include <iostream>
using namespace std;
int main()
{
//1.启动SOCKET库,版本为2.0
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
cout << "Socket2.0初始化失败,Exit!";
return 0;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
{
WSACleanup();
return 0;
}
//2.创建socket,
SOCKET sock; //socket
sock = socket(
AF_INET, //internetwork: UDP, TCP, etc
SOCK_DGRAM, //SOCK_DGRAM说明是UDP类型
0 //protocol
);
if (sock == INVALID_SOCKET) {
cout << "Socket 创建失败,Exit!";
return 0;
}
//3.设置发往的地址
SOCKADDR_IN addrto; //发往的地址
memset(&addrto, 0, sizeof(addrto));
addrto.sin_family = AF_INET;
// https://jingyan.baidu.com/article/1709ad8041dca64634c4f006.html
//去掉SDL检查。设置项目属性,将c/c++->SDL检查设置为“否”即可跳过检查,使用旧的函数可编译成功。
addrto.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //旧函数,不设置sdl检查会报错
//端口号必须和服务器绑定的端口号一致
addrto.sin_port = htons(7861);
//4.发送消息
int nlen = sizeof(addrto);
unsigned int uIndex = 1;
char szMsg[] = "this is a UDP test package";//被发送的字段
while (true)
{
Sleep(1000);
if (sendto(sock, szMsg, strlen(szMsg), 0, (SOCKADDR*)&addrto, nlen)
== SOCKET_ERROR)
cout << WSAGetLastError() << endl;
else
cout << uIndex++ << ":an UDP package is sended." << endl;
if (uIndex > 10)break;
}
//if (!closesocket(sock))
//{
// WSAGetLastError();
// return 0;
//}
//if (!WSACleanup())
//{
// WSAGetLastError();
// return 0;
//}
cout << "客户端关闭" << endl;
closesocket(sock);
WSACleanup();
return 0;
}