udp客户端和服务器代码,支持ipv6。

getaddrinfo这个函数隐藏了ipv4和ipv6的具体细节,强烈推荐使用。设置hints.ai_family = AF_UNSPEC后,getaddrinfo可以根据ip地址自动判断是ipv4还是ipv6。当然也可以使用hints.ai_family = AF_INET6直接指定为ipv6。

同时getnameinfo也是同时支持ipv4和ipv6的函数,建议使用。



服务器代码:

#include "stdafx.h"
#include <winsock2.h>
#include <iostream>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{
	WSADATA wd{};
	auto err = WSAStartup(MAKEWORD(2, 2), &wd);
	if (0 != err)
	{
		return 0;
	}

	addrinfo *result = nullptr;
	addrinfo hints = {};
	hints.ai_socktype = SOCK_DGRAM;  //数据报
	hints.ai_protocol = IPPROTO_UDP; //udp 
	hints.ai_family = AF_UNSPEC;     //协议无关 
	hints.ai_flags = AI_PASSIVE;     //用于服务端bind,用于bind这个参数必须设置

	//第一个参数为nullptr或0.0.0.0,表示监听本地所有网卡数据,0.0.0.0表示只能为ipv4。
	//或者hints.ai_family = AF_INET;也表示使用ipv4
	auto dwRetval = getaddrinfo("0.0.0.0" /*本地所有网卡,ipv4*/, "3000"/*端口号为3000*/, &hints, &result);
	if (0 != dwRetval)
	{
		return 0;
	}

	auto s = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (INVALID_SOCKET == s)
	{
		return 0;
	}
	

	err = bind(s, result->ai_addr, result->ai_addrlen);
	if (0 != err)
	{
		return 0;
	}

	int nSendSize = result->ai_addrlen;
	sockaddr *remoteAddr = reinterpret_cast<sockaddr *>(new char[nSendSize]);

	char buffer[1000] = {};

	while (true)
	{
		int nSendSizeTemp = nSendSize;
		auto ret = recvfrom(s, buffer, sizeof(buffer), 0, remoteAddr, &nSendSizeTemp); //接收来自客户端的数据

		if (0 == ret || SOCKET_ERROR == ret)
		{
			break;
		}
		ret = sendto(s, buffer, ret, 0, remoteAddr, nSendSizeTemp);  //发往客户端
		if (0 == ret || SOCKET_ERROR == ret)
		{
			break;
		}

		char szIp[200] = {};
		char szPort[200] = {};
		ret = getnameinfo(result->ai_addr, result->ai_addrlen, szIp, sizeof(szIp), szPort, sizeof(szPort), NI_NUMERICSERV | NI_NUMERICHOST);
		if (0 != ret)
		{
			return 0;
		}

		std::cout << szIp << ":" << szPort << "," << buffer << std::endl;
	}

	delete[] reinterpret_cast<char*>(remoteAddr);

	closesocket(s);
	WSACleanup();

	return 0;
}



客户端代码

#include "stdafx.h"
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

#include <iostream>

int main()
{
	bool bConnect = true;  //使用upd的两种方式
	WSADATA wd{};
	auto err = WSAStartup(MAKEWORD(2, 2), &wd);
	if (0 != err)
	{
		return 0;
	}

	addrinfo *result = nullptr;
	addrinfo hints = {};
	hints.ai_socktype = SOCK_DGRAM;   //数据报
	hints.ai_protocol = IPPROTO_UDP;  //udp 
	hints.ai_family = AF_UNSPEC;	  //协议无关 
	auto dwRetval = getaddrinfo("127.0.0.1","3000",&hints,&result); //127.0.0.1 为服务器ip,并且表明是ipv4。3000 为服务器端口号
	if (0 != dwRetval)
	{
		return 0;
	}

	auto s = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (INVALID_SOCKET == s)
	{
		return 0;
	}	

	char buffer[] = "你好啊呵呵";
	char bufferRecv[1024] = {};

	//udp两种方式
	if (bConnect)  //第一种,使用connect
	{
		auto ret = connect(s, result->ai_addr, result->ai_addrlen);
		if (0 != ret)
		{
			return 0;
		}

		for (int i = 0; i != 10 ; i++)
		{
			ret = send(s, buffer, sizeof(buffer), 0);
			if (SOCKET_ERROR == ret)
			{
				return 0;
			}

			ret = recv(s, bufferRecv, sizeof(bufferRecv), 0);
			if (SOCKET_ERROR == ret)
			{
				return 0;
			}
	
			char szIp[200] = {};
			char szPort[200] = {};			
			ret = getnameinfo(result->ai_addr, result->ai_addrlen,szIp, sizeof(szIp), szPort, sizeof(szPort), NI_NUMERICSERV | NI_NUMERICHOST);
			if (0 != ret)
			{
				return 0;
			}
			std::cout << szIp << ":" << szPort << "," << bufferRecv << std::endl;
		}
	
	}
	else //第二种,不使用connect
	{
		for (int i = 0; i != 10; i++)
		{
			auto ret = sendto(s, buffer, sizeof(buffer), 0, result->ai_addr, result->ai_addrlen);
			if (SOCKET_ERROR == ret)
			{
				return 0;
			}

			int nSendSize = result->ai_addrlen;
			sockaddr *remoteAddr2 = reinterpret_cast<sockaddr *>(new char[nSendSize]);			
			ret = recvfrom(s, bufferRecv, sizeof(bufferRecv), 0, remoteAddr2, &nSendSize);
			if (SOCKET_ERROR == ret)
			{
				return 0;
			}
		
			char szIp[200] = {};
			char szPort[200] = {};
			ret = getnameinfo(remoteAddr2, nSendSize, szIp, sizeof(szIp), szPort, sizeof(szPort), NI_NUMERICSERV | NI_NUMERICHOST);
			if (0 != ret)
			{
				return 0;
			}
			std::cout << szIp << ":" << szPort << "," << bufferRecv << std::endl;
			delete[] reinterpret_cast<char*>(remoteAddr2);
		}	
	}

	getchar();

	closesocket(s);
	WSACleanup();

    return 0;
}



SixMan 这是上次IPv6文件传输的升级版,新特性如下: 1.加入了即时通信,也许只是鸡肋,大家别BS我啊 2.支持文件夹传输 3.解决上一版中,有些情况下只能单向传文件的重大缺陷,现在只要双方建立了连接,无论哪方发起的连接,只要连接建立就能互传文件... 使用方法: 点击 添加用户-> 双击“新加入的用户” -> 在弹出的聊天窗口 输入 对方(不是你自己的) IP(v6) -> 点击 连接 -> 等待连接成功后 即可 发送文件时 只需将待发送的文件(夹)拖拽的窗口即可 点击 查看本机IP 按键可以查看本机的IP地址信息,其结果取自在cmd窗口运行ipconfig命令的结果 设置按钮里 可以修改昵称 有朋友说还要知道对方IP才能连接,太麻烦了... 问这个问题的朋友可能不太了解现在的网络协议等相关知识,没有网络地址是无法通信的,两个点要想通信必须要知道对方网络地址才行, 可能有朋友不服气,说为什么QQ就不用,这个问题只要懂一点计算机知识的人都知道,人家腾讯有钱,把用户登录服务放在一个有着固定公网 IP的服务器上,这个IP永不会变,你的QQ客户端内部是集成了这个IP的,所以你登陆时不需要你输入IP,而且所有QQ用户都是通过这一个服务器登录, 腾讯的数据库保存着所有QQ用户的个人信息和好友列表... 我可没有钱去置办那么庞大的服务器和数据库,而且我的软件不是QQ那样的商业软件,不过是为了解决平时一些应用而开发的一款小工具,应用范围是不同于 QQ的,也根本不是用来代替QQ的.... 注意: 假设A和B通信 那么只要A连接到B 或者 B连接到A 即可,无需双向连接,连接后即可双向传文件 有时连接不成功可以换一个IP(v6)地址,一般情况下会有多个IPv6地址,一个不行换一个试试,再不行要关闭防火墙。 遇到问题可以找客服 QQ:191730977 Email: acmtiger@gmail.com 感谢大家的支持
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值