TCP服务端IPv6
// StudyC++Sokcet.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<winsock2.h>//winsock2.0的头文件,链接windows的动态库
#include<ws2tcpip.h>//sockaddr_in6的头文件
using namespace std;//命名空间
//指定动态库的lib文件
#pragma comment(lib,"ws2_32.lib")
//TCP服务端IPv6版本
int main()
{
//初始化winsock2.2相关的动态库
WSADATA wd;//获取Socket相关信息
if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//0标识成功 MAKEWORD版本
{
cout << "WSAStartup error:" << WSAGetLastError() << endl;//WSAGetLastError()获取错误
}
//
//TCP Server的代码结构
//1.创建TCP socket 流式套接字
SOCKET s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)//创建失败,返回错误信息
{
cout << "socket error:" << WSAGetLastError() << endl;
return 0;
}
//2.绑定socket到一个IP地址和端口
sockaddr_in6 addr;
memset(&addr, 0, sizeof(sockaddr_in6));
addr.sin6_port = htons(8000);//网络字节序,端口号
addr.sin6_family = AF_INET6;//地址族
//addr.sin6_addr = in6addr_any;//in6addr_any表示绑定任意ip地址(IPv6)
//cmd ipconfig 查询本机IPv6地址
inet_pton(AF_INET6, "fe80::7848:74a5:180a:a15b%12",&addr.sin6_addr);//绑定指定地址
int len = sizeof(sockaddr_in6);//指定大小
if (bind(s, (sockaddr*)&addr, len) == SOCKET_ERROR)//(sockaddr*)强制转换
{
//有时socket端口被占用了,也没办法bind就会返回错误
cout << "bind error:" << WSAGetLastError() << endl;
return 0;
}
//3.监听
//s套接字,5也可用一个宏,表示正在等待完成相应TCP三路握手过程的队列长度
if (listen(s, 5) == SOCKET_ERROR)
{
cout << "listen error:" << WSAGetLastError() << endl;
return 0;
}
//4.接受客户端请求,并且返回和客户端通讯的套接字
sockaddr_in6 addrClient;
memset(&addrClient, 0, sizeof(sockaddr_in6));
int lenClient = sizeof(addrClient);
SOCKET c = accept(s, (sockaddr*)&addrClient, &lenClient);//成功返回clinet端的套接字
if (c == INVALID_SOCKET)
{
cout << "accept error" << WSAGetLastError() << endl;
return 0;
}
//5.发送、接收消息
int ret = 0;
do
{ //向客户端发送数据,不能用监听套接字,要用返回套接字
ret = send(c, "I am Server!", strlen("I am Server!"), 0);//把flag置0
//接收客户端的消息
char buf[64] = { "\0" };//初始化以免乱码
ret = recv(c, buf, 64, 0);//把flag置0
//cout << "recv:" << inet_ntoa(addrClient.sin_addr) << " : " << buf << endl;//inet_ntoa转化为IP字符串
char ipbuf[20] = { 0 };
inet_ntop(AF_INET6, (LPVOID)&addrClient.sin6_addr, ipbuf, 100);
cout << "recv:" << ipbuf << " : " << buf << endl;
} while (ret != SOCKET_ERROR && ret != 0);//成功返回接收到的字节数,错误返回SOCKET_ERROR,
//对方关闭连接返回0,否则认为对方一直发送,我方循环接收
//清理winsock环境
//6.关闭套接字
closesocket(s);
///
WSACleanup();
return 0;
///
}
TCP客户端IPv6
// TCP_Clinet.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<winsock2.h>//winsock2.0的头文件,链接windows的动态库
#include<ws2tcpip.h>//sockaddr_in6的头文件
using namespace std;//命名空间
//指定动态库的lib文件
#pragma comment(lib,"ws2_32.lib")
//TCP客户端IPv6
int main()
{
//初始化winsock2.2相关的动态库
WSADATA wd;//获取Socket相关信息
if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//0标识成功 MAKEWORD版本
{
cout << "WSAStartup error:" << WSAGetLastError() << endl;//WSAGetLastError()获取错误
}
//
//TCP Clinet的代码结构
//1.创建TCP socket 流式套接字
SOCKET s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);//地址族,套接字类型,协议----成功返回一个socket
if (s == INVALID_SOCKET)//创建失败,返回错误信息
{
cout << "socket error:" << WSAGetLastError() << endl;
return 0;
}
//2.链接服务端
sockaddr_in6 addr;//sockaddr变种
memset(&addr,0,sizeof(sockaddr_in6));
addr.sin6_port = htons(8000);//网络字节序,端口号
//指定连接的服务器如果用any步子到用什么服务器
inet_pton(AF_INET6, "fe80::7848:74a5:180a:a15b%12", &addr.sin6_addr);
addr.sin6_family = AF_INET6;//地址族
int len = sizeof(sockaddr_in6);//指定大小
if (connect(s, (sockaddr*)&addr, len) == SOCKET_ERROR)
{
cout << "connect error:" << WSAGetLastError() << endl;
return 0;
}
//3.接收发送消息
int ret = 0;
do
{
//接收客户端的消息
char buf[64] = { "\0" };
ret = recv(s, buf, 64, 0);//把flag置0
char ipbuf[100] = { 0 };
inet_ntop(AF_INET6, (LPVOID)&addr.sin6_addr, ipbuf, 100);
cout << "recv" << ipbuf << ": " << buf << endl;//inet_ntoa
//发送
ret = send(s, "i am Client!", strlen("i am Client!"), 0);
Sleep(1000);
} while (ret != SOCKET_ERROR && ret != 0);
//4.关闭套接字
closesocket(s);
///
WSACleanup();
return 0;
///
}
先运行TCP_Server.exe,在运行TCP_Clinet.exe