实现效果
查看电脑端口号
windows环境下查看当前电脑端口号:netstat -an
// 有的时候绑定失败,是因为端口被占用
UDP流程图
函数注解
socket()
int socket(int domain, int type, int protocol);
- domain: 指定协议族(多个协议的统称,包含IP-TCP-UDP-FTP-SMTP等)和地址族。
一般可定义为AF_INET、AF_INET6、AF_UNIX;
AF--address family缩写,AF_INET表示IPv4、AF_INET6表示IPV6、AF_UNIX;
- type:指定套接字的类型,例如SOCK_STREAM,SOCK_DGRAM;SOCK_STREAM:
流式套接字,提供面向连接的可靠传输;
SOCK_DGRAM:数据报套接字,提供无连接不可靠传输;
- protocol:指定传输协议,常用的有IPPROTO_TCP和IPPTOTO_UDP,分别表示TCP和UDP传输协议;
具体的协议编号,通常为0表示自动选择合适的协议;
- 返回值:
成功,新套接字所对应的文件描述符;
失败,-1 errno;
sendto()
int sendto(int s, const void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen);
s:标识的一个套接字的描述符;
sockfd:要发送数据的套接字描述符。
buf:指向要发送的数据的缓冲区。
len:要发送的数据长度。
flags:选项标志,可以为0或者MSG_DONTWAIT等。
dest_addr:目标地址的sockaddr结构体指针。
addrlen:目标地址结构体的长度。
recvfrom()
//recv()用来接收远程主机经指定的;
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr*from,int *fromlen);
socket:传来的数据,并把数据存到由参数;
buf:指向的内存空间,参数;
len:为可接收数据的最大长度,参数;
flags:一般设 0,其他数值定义请参考 recv0).参数;
from:用来指定欲传送的网络地址,结构 sockaddr 请参考 bind();
fromlen:sockaddr 的结构长度;
返回值:成功则返回接收到的字符数,失败则返回-1,错误原因存于errno 中;
程序demo–client
//下载一个“SocketTool V4.exe”软件,模拟UDP_server
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
using namespace std;
//添加动态库的lib
#pragma comment(lib, "ws2_32.lib")
int main()
{
SOCKET m_Socket;
SOCKADDR_IN m_RemoteAddress; //远程地址
int m_RemoteAddressLen;
// socket环境
//用于存储被WSAStartup函数调用后返回的windows sockets数据,它包含了Winsock.dll执行的数据
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup error:" << GetLastError() << endl;
return false;
}
// 远端地址
const char* ip = "192.168.236.1";
int port =111;
m_RemoteAddress.sin_family = AF_INET;
m_RemoteAddress.sin_port = htons(port);
m_RemoteAddressLen = sizeof(m_RemoteAddress);
inet_pton(AF_INET, ip, &m_RemoteAddress.sin_addr);
// socket对象
m_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (m_Socket == INVALID_SOCKET)
{
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
return false;
}
// 接收和发送
char recvBuf[1024] = { 0 };
char sendBuf[1024] = "Nice to meet you!";
while (1) {
int sendLen = sendto(m_Socket, sendBuf, strlen(sendBuf), 0, (sockaddr*)&m_RemoteAddress, m_RemoteAddressLen);
if (sendLen > 0)
{
cout << "发送到远程端的信息: " << sendBuf << endl;
}
int recvLen = recvfrom(m_Socket, recvBuf, 1024, 0, NULL, NULL);
if (recvLen > 0)
{
cout << "接收到一个信息: " << recvBuf << endl;
}
}
closesocket(m_Socket);
WSACleanup();
return true;
}
问题
编译环境: QT+VS2017
原因: 开源库使用到的Windows自带<Winsock.h>,导致再调用#include<Winsock2.h>时,内部函数会因重复而冲突。
解决办法:
“项目”——》“属性”——》“C/C++”——》“预处理器”——》“预处理定义”——》添加“WIN32_LEAN_AND_MEAN”——》“确定”
WIN32_LEAN_AND_MEAN