win操作系统C++语言 socket,udp通信
本文用于记录win操作系统,C++语言,socket,udp通信
服务端流程
首先要加载套接字库
- 创建套接字
- 服务端地址
- bind 套接字与地址绑定
- recvfrom 等待并接收数据
- sendto 发送数据
- 资源关闭
服务端代码示例
// udpsrv.cpp
#include<stdio.h>
#include <iostream>
#include <WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
int main()
{
WORD wVersionRequested;//unsigned short
WSADATA wsaData;//这个结构被用来存储被WSAStartup函数调用后返回的Windows Sockets数据
int err;
wVersionRequested = MAKEWORD(1,1);
//WSAStartup就是为了向操作系统说明,我们要用哪个库文件,让该库文件与当前的应用程序绑定,从而就可以调用该版本的socket的各种函数了
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)//低字节为主版本,高字节为副版本
{
WSACleanup();
return -1;
}
//.......以上为准备环境....以下为具体服务端udp通讯流程..........
std::cout << "server is operating!\n\n";
//1.创建套接字
SOCKET socketSrv = socket(AF_INET, SOCK_DGRAM, 0);
//2.服务端地址
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", (void *)&addrSrv.sin_addr.S_un.S_addr);
addrSrv.sin_port = htons(6000);
//3.套接字绑定
bind(socketSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
SOCKADDR_IN addrClient;//用来接收客户端地址信息
char ClientIP[20];
int len = sizeof(SOCKADDR);
char recvBuf[100];
char sendBuf[100];
char tempBuf[100];
while (1)
{
//4.等待并接收数据
recvfrom(socketSrv, recvBuf, 100, 0, (SOCKADDR*)&addrClient, &len);
if ('q' == recvBuf[0])
{
sendto(socketSrv, "q", strlen("q") + 1, 0, (SOCKADDR*)&addrClient, len);
std::cout << "chat end!\n\n";
break;
}
inet_ntop(AF_INET, (void *)&addrClient.sin_addr, ClientIP, 16);
sprintf_s(tempBuf, "%s say : %s", ClientIP, recvBuf);
printf("%s\n",tempBuf);
//5.发送数据
std::cout << "Please input data:";
gets_s(sendBuf);
sendto(socketSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, len);
}
//6.关闭资源
closesocket(socketSrv);
WSACleanup();
return 0;
}
客户端流程
首先要加载套接字库
- 创建用于监听的套接字
- 确定服务端通讯地址信息
- sendto 发送数据
- recvfrom 等待并接收数据
- 资源关闭
// udpclient.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<stdio.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
int main()
{
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 || //低字节为主版本
HIBYTE(wsaData.wVersion) != 1) //高字节为副版本
{
WSACleanup();
return -1;
}
printf("Client is operating!\n\n");
//1.创建用于监听的套接字
SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
//2.确定服务端通讯地址信息
sockaddr_in addrSrv;
inet_pton(AF_INET, "127.0.0.1", (void *)&addrSrv.sin_addr.S_un.S_addr);
//addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//输入你想通信的她(此处是本机内部)
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
int len = sizeof(SOCKADDR);
char recvBuf[100]; //收
char sendBuf[100]; //发
char tempBuf[100]; //存储中间信息数据
while (1)
{
printf("Please input data: ");
gets_s(sendBuf);
//3.发送数据
sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, len);
//4.等待数据
recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrSrv, &len);
if ('q' == recvBuf[0])
{
sendto(sockSrv, "q", strlen("q") + 1, 0, (SOCKADDR*)&addrSrv, len);
printf("Chat end!\n");
break;
}
sprintf_s(tempBuf, "%s say : %s", "server", recvBuf);
printf("%s\n", tempBuf);
}
closesocket(sockSrv);
WSACleanup();
return 0;
}
遇到的问题
-
错误:error C4996: ‘inet_addr’: Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings 原因:在VS2013以后的版本中,增加了inet_pton()、InetPton()之类的新函数,用于IP地址在“点分十进制”和“二进制整数”之间转换,并且能够处理ipv4和ipv6。而inet_addr是老函数,高版本VS在编译时默认使用了新函数,所以会报该错误。 解决办法: inet_pton(AF_INET, "127.0.0.1", (void *)&addrSrv.sin_addr.S_un.S_addr);
//addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//输入你想通信的她(此处是本机内部)
-
错误:C4996 ‘inet_ntoa’: Use inet_ntop() or InetNtop() instead or define 原因:同上 解决办法: inet_ntop(AF_INET, (void *)&addrClient.sin_addr, ClientIP, 16);
-
错误LNK2019: 无法解析的外部符号 _WSAStartup@8,该符号在函数 _main 中被引用
原因:编译器没有链接到我们想要的头文件运行库
解决办法:#pragam 编译器指令,指示编译器链接到<winsock.h>的库文件ws2_32.lib,即**#pragma comment(lib,“ws2_32.lib”)**
#pragma comment(lib,"ws2_32.lib")
问题总结
第一类问题是主机字节序列与网络字节序列转换函数的版本问题
第二类是编译问题
程序运行效果图
|