sweetyy、

导航

UDP通信实验

UDP通信实验

一、 实验目的

1.进一步理解Winsock编程接口的调用方法。

2.了解UDP协议的工作原理,掌握UDP服务端程序和客户端程序的编写过程,熟悉程序的测试方法。

二、 实验仪器

Visual Studio软件

三、 实验内容

1.调试实验带的代码,使之能运行。

2.修改代码使服务端和客户端能互发信息,并能正确接受到。

3.进一步修改代码,当任何一方发送字符“bye”时程序就结束。

四、 实验步骤

1、新建UDPServer项目

2、新建UDPClient项目

注意:①客户端与服务器不能放在同一个项目中,否则会出现重复定义而报错。

​ ②要与对方通信,对方ping得到ip,修改成对方ip即可。

五、 实验基本原理(原理/源程序)

1、UDPServer

// server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"WS2_32") //连接数据库
using namespace std;
class CInitSock
{
public:
    //初始化socket   两个默认参数 指明两个版本号 大版本号  小版本号 
	CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
	{
		WSADATA wsaData;
		//版本号变成一个打包字
		WORD sockVersion = MAKEWORD(minorVer, majorVer);
//用来当缺省的返回参数.指针返回到对应的结果不为0表示初始化失败.否则表示初始化成功
		if (::WSAStartup(sockVersion, &wsaData) != 0)
		{
			exit(0);
		}
	}
	~CInitSock() //释放
	{
		::WSACleanup();
	}

};
CInitSock initSock;		// 初始化Winsock库

int main()
{
	// 创建套节字
	SOCKET s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	//参数一:协议簇  参数二:采用无连接方式   参数三:具体是什么协议
	/*
	Value1 :表示TCP/IP协议组
	Value2 :表示对于socket的读写是一种无连接的读取方式
	Value3 :表示具体的协议名称
	*/

	if (s == INVALID_SOCKET)
	{
		printf("Failed socket() \n");
		return 0;
	}

	// 填充sockaddr_in结构
	sockaddr_in sin;  //结构分量进行初始化
	sin.sin_family = AF_INET;    //协议簇
	sin.sin_port = htons(4567);  //端口号
	//服务器端IP地址 (加上对应的端口号)  代表0.0.0.0(任意地址)   
	sin.sin_addr.S_un.S_addr = INADDR_ANY;

	// 绑定这个套节字到一个本地地址
	if (::bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("Failed bind() \n");
		return 0;
	}

	// 接收数据
	char buff[1024];  //缓冲池
	sockaddr_in addr;
	int nLen = sizeof(addr);
	while (TRUE)
	{
		int nRecv = ::recvfrom(s, buff, 1024, 0, (sockaddr*)&addr, &nLen);
//接收函数,S代表套接字(填充好了端口)最大长度 最小长度 读取UDP客户端的ip地址 
		if (nRecv > 0)
		{
			buff[nRecv] = '\0';  //填充截止符
//地址转化为字符串  点分十进制  ::inet_ntoa(addr.sin_addr)
			printf(" 接收到数据(%s):%s", ::inet_ntoa(addr.sin_addr), buff);
			//如果对方发送的字符是bye  结束
			if (strcmp(buff, "bye") == 0)
				break;
			char szText[1024];
			cin >> szText;
			//服务器端发送给客户端    发送给指定的ip地址 
			::sendto(s, szText, strlen(szText), 0, (sockaddr*)&addr, sizeof(addr));
		}
	}
	printf("\n");
	::closesocket(s);
}

2、UDPClient

// client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include<iostream>
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"WS2_32")
using namespace std;
class CInitSock
{
public:
	CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
	{
		WSADATA wsaData;
		WORD sockVersion = MAKEWORD(minorVer, majorVer);
		if (::WSAStartup(sockVersion, &wsaData) != 0)
		{
			exit(0);
		}
	}
	~CInitSock()
	{
		::WSACleanup();
	}

};


CInitSock initSock;		// 初始化Winsock库

int main()
{
	// 创建套节字
	SOCKET s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == INVALID_SOCKET)
	{
		printf("Failed socket() %d \n", ::WSAGetLastError());
		return 0;
	}

	// 也可以在这里调用bind函数绑定一个本地地址
	// 否则系统将会自动安排

	// 填写远程地址信息
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(4567);
	// 注意,这里要填写服务器程序所在机器的IP地址
	// 如果你的计算机没有联网,直接使用127.0.0.1即可
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	char buff[1024];
	int nLen = sizeof(addr);
	while (TRUE)
	{
		// 发送数据
		char szText[1024];  //定义一个大小为1024的缓冲
		cin >> szText;   //发送
		::sendto(s, szText, strlen(szText), 0, (sockaddr*)&addr, sizeof(addr)); //发送的地址是通过addr
		int nRecv = ::recvfrom(s, buff, 1024, 0, (sockaddr*)&addr, &nLen);
		if (nRecv > 0)
		{
			buff[nRecv] = '\0';
			printf(" 接收到数据(%s):%s", ::inet_ntoa(addr.sin_addr), buff);
		}
		if (strcmp(buff, "bye") == 0)
			break;
	}
	printf("\n");
	::closesocket(s);
	return 0;
}

六、实验结果

1、与自己电脑通信

2、与其他电脑通信

posted on 2022-05-18 16:42  sweetyy、  阅读(41)  评论(0)    收藏  举报