客户端:
// UDP_Client.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
/*****************************************/
/****(1)初始化WSA***********************/
/*****************************************/
WSADATA data;
/*MAKEWORD(bLow,bHigh) 将bLow与bHigh两个字节合并成一个word型,bLow 在低位,bHigh在高位 */
WORD wVersionRequested = MAKEWORD(2, 0);
/*WSAStartup(WORD,LPWSADATA)
WORD指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本
LPWSADATA 操作系统利用第二个参数LPWSADATA返回请求的Socket的版本信息
*/
WSAStartup(wVersionRequested, &data);
/*****************************************/
/****(2)创建套接字(socket)************/
/*****************************************/
/*socket( domain, type,protocol);
domain:协议域,又称协议族(family) AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合
type:指定Socket类型 数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用
protocol:指定协议 IPPROTO_UDP对应UDP传输协议
*/
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
printf("Client is setup and now trying to connect server...\n");
/*****************************************/
/****(3)连接到服务器********************/
/*****************************************/
sockaddr_in addrServer;
int nSockAddrSize = sizeof(addrServer);
sockaddr_in addr;
addr.sin_family = AF_INET; /*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/
addr.sin_port = htons(75); /*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 设置套接字的主机IP地址为 127.0.0.1
//inet_addr() 根据点十进制格式表示的IP地址返回一个适合分配给S_addr的u_long型数值
/*****************************************/
/****(4)发送和接受数据******************/
/*****************************************/
//发送
/*sendto( s, buf, len, flags, to, tolen)
s: (可能已建立连接)套接字描述符
buf:指向缓冲区的指针,该缓冲区包含将要发送的数据
len:指定缓冲区中数据的长度
flags:设定的值影响函数调用的行为,一般设置为0即可
to:可选指针,指定目标套接字的地址
tolen:目标套接字的地址的长度
*/
/*
recvfrom( s, buf, len, flags, from, fromlen)
s:准备接受数据的套接字
buf:指向缓冲区的指针
len:缓冲区的长度
flags:设定的值将影响函数的行为,一般设置为0即可
from:指向地址结构体的指针,用于接受发送数据方的地址信息
fromlen:整型指针,in/out类型参数,
*/
static const char szSendToServer[] = "Hello! I'm trying to connect you!";
char szBuff[50] = { 0 };
sendto(s, szSendToServer, sizeof(szSendToServer), 0, (sockaddr*)&addr , nSockAddrSize);
recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrServer, &nSockAddrSize);
printf("%s\n", szBuff);
/*****************************************/
/****(5)关闭套接字(断开连接)**********/
/*****************************************/
closesocket(s);
WSACleanup();
/*之后如果还有输入(鼠标/键盘),退出程序*/
if (getchar()) return 0;
return 0;
}
服务端:
// UDP_Server.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
/*****************************************/
/****(1)初始化WSA***********************/
/*****************************************/
WSADATA data;
/*MAKEWORD(bLow,bHigh) 将bLow与bHigh两个字节合并成一个word型,bLow 在低位,bHigh在高位 */
WORD wVersionRequired = MAKEWORD(2, 0);//wVersionRequired为值为2的无符号短word型,低位为2,高位为0
/*WSAStartup(WORD,LPWSADATA)
WORD指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本
LPWSADATA 操作系统利用第二个参数LPWSADATA返回请求的Socket的版本信息
*/
WSAStartup(wVersionRequired, &data);
//
/*****************************************/
/****(2)创建套接字(socket)************/
/*****************************************/
/*socket( af, type,protocol);
af:指定地址族
type:指定Socket类型 数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用
protocol:指定协议 IPPROTO_UDP对应UDP传输协议
*/
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
/*socket(AF_INET, SOCK_DGRAM, 0);
AF_INET:对于TCP/IP协议的套接字,只能是 AF_INET
SOCK_DGRAM:SOCK_DGRAM产生数据报套接字
0:系统根据地址格式与套接字类别,自动选择一个合适的协议
*/
/*****************************************/
/*(3)将套接字绑定到一个本地地址与端口上*/
/*****************************************/
sockaddr_in addr;
addr.sin_family = AF_INET; /*指定地址家族 对于TCP/IP协议的套接字,必须设置为AF_INET */
addr.sin_port = htons(75); /*指定将要分配给套接字的端口(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
addr.sin_addr.S_un.S_addr = INADDR_ANY; //套接字的主机IP地址
//INADDR_ANY允许套接字向任何分配给本机的IP地址发送或接受数据,允许一个独立应用接受发自多个接口的回应
/*bind(s,name,namelen) 此函数将本地地址与套接字关联
s:一个未绑定套接字描述符的识别符
name:分配给sockaddr结构中套接字的地址
namelen:name参数中数值的长度
*/
bind(s, (sockaddr*)&addr, sizeof(addr));
printf("Server is setup and now waiting for clients' request...\n");
sockaddr_in addrClient; //客户端的地址
int nSockAddrSize = sizeof(addrClient);
/*sendto( s, buf, len, flags, to, tolen)
s: (可能已建立连接)套接字描述符
buf:指向缓冲区的指针,该缓冲区包含将要发送的数据
len:指定缓冲区中数据的长度
flags:设定的值影响函数调用的行为,一般设置为0即可
to:可选指针,指定目标套接字的地址
tolen:目标套接字的地址的长度
*/
/*
recvfrom( s, buf, len, flags, from, fromlen)
s:准备接受数据的套接字
buf:指向缓冲区的指针
len:缓冲区的长度
flags:设定的值将影响函数的行为,一般设置为0即可
from:指向地址结构体的指针,用于接受发送数据方的地址信息
fromlen:整型指针,in/out类型参数,
*/
/*****************************************/
/*(4)检测是否收到客户端发出的数据,如果接收到就显示接收到的数据,并向客户端发送一个数据进行交互*/
/*****************************************/
static const char szAnswerClient[] = "Hello! You've been connected!";
char szBuff[50] = { 0 };
if (recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrClient, &nSockAddrSize) > 0)
//szBuff[50] = { 0 };
//如果接收到来自客户端的信息
{
printf("There is one client(%s) connected!\n", inet_ntoa(addrClient.sin_addr));
//inet_ntoa() 接受一个in_addr结构体参数,返回一个以点分十进制格式表示的IP地址字符串
printf("%s\n", szBuff);//显示接收到的数据
sendto(s, szAnswerClient, sizeof(szAnswerClient), 0, (sockaddr*)&addrClient, nSockAddrSize);
//向客户端发送"Hello! You've been connected!"以表示连接成功
//szAnswerClient[] = "Hello! You've been connected!";
}
/*****************************************/
/****(5)关闭套接字(断开连接)**********/
/*****************************************/
closesocket(s);
WSACleanup();
/*之后如果还有输入(鼠标/键盘),退出程序*/
if (getchar()) return 0;
return 0;
}