C++ UDP

本文详细介绍了如何在C++中使用socket(),sendto(),和recvfrom()函数进行UDP通信,包括创建套接字、设置目标地址、发送和接收数据,以及解决在VS2017中使用Winsock库的编译冲突问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现效果

在这里插入图片描述

查看电脑端口号

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在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值