23Socket实现UDP服务器端和客户端连接传输

客户端

23UdpClient.cpp
代码:
// 23UdpClient.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"


#include <stdio.h>
//Windows套接字所需的头文件
#include <WINSOCK.H>
//Windows套接字接口的库文件
#pragma comment(lib, "WSOCK32.LIB")


//程序使用的WinSock主版本
#define SOCK_VER 2
//变量和函数声明
SOCKET g_sock = 0;
void ErrMsg(DWORD dwErr);



int _tmain(int argc, _TCHAR* argv[])
{
	//初始化WinSock环境
	WSADATA wd = {0};
	int nStart = WSAStartup(MAKEWORD(SOCK_VER, 0), &wd);
	if(nStart = 0)
	{
		//初始化失败
		return 0;
	}
	//检测当前系统的WinSock版本是否支持所需版本
	if(LOBYTE(wd.wVersion) != 2)
	{
		return 0;
	}
	//创建一个UDP Socket
	g_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(g_sock == INVALID_SOCKET)
	{
		ErrMsg(WSAGetLastError());
		return 0;
	}
	printf("Socket创建成功\n");
	//发数据的目标地址
	sockaddr_in addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2800);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	//发出数据包
	char szBuff[] = "hello UDP!";
	int nSent = sendto(g_sock, szBuff, strlen(szBuff) + 1, 0, (sockaddr *)&addr, sizeof(addr));
	if(nSent == 0)
		ErrMsg(WSAGetLastError());
	else
		printf("信息成功发出,等待回应...\n");
	//等待回应
	sockaddr_in saServer = {0};
	int nFromLen = sizeof(saServer);
	*szBuff = '\0';
	int nRecv = recvfrom(g_sock, szBuff, 256, 0, (sockaddr *)&saServer, &nFromLen);
	if(SOCKET_ERROR == nRecv)
		ErrMsg(WSAGetLastError());
	else
		printf("收到回应:%s 从%s,%d\n", szBuff, inet_ntoa(saServer.sin_addr), ntohs(saServer.sin_port));
	//关闭套接字
	closesocket(g_sock);
	//等待用户输入
	system("pause");
	//清理SOCKET环境
	WSACleanup();
	return 0;
}
//获取错误详细信息,并输出
void ErrMsg(DWORD dwErr)
{
	char szErr[1024] = {0};
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szErr, 1024, NULL);
	printf(szErr);
}

VS2010下出现错误:
1>f:\program\vc++实例精通\23udpclient\23udpclient\23udpclient.cpp(75): error C2664: “FormatMessageW”: 不能将参数 5 从“char [1024]”转换为“LPWSTR”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
项目-属性-常规-字符集:改为使用多字节字符集
重新编译出现错误
1>LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

项目-属性-配置 属性-清单工具-输入和输出-嵌入清单:是改为否

编译执行:


服务器端

UdpServer.cpp代码:

// 23UdpServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <stdio.h>
//使用WinSock所需的头文件
#include <WINSOCK.H>
//使用WinSock所需的库文件
#pragma comment(lib, "WSOCK32.LIB")

//程序中要使用的WinSock主版本
#define SOCK_VER 2
//变量和函数声明
SOCKET g_sock = 0;
void ErrMsg(DWORD dwErr);


int _tmain(int argc, _TCHAR* argv[])
{
	//初始化环境
	WSADATA wd = {0};
	int nStart = WSAStartup(MAKEWORD(SOCK_VER, 0), &wd);
	if(nStart = 0)
	{
		return 0;
	}
	if(LOBYTE(wd.wVersion) != 2)
	{
		return 0;
	}
	//创建SOCKET
	g_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(g_sock == INVALID_SOCKET)
	{
		ErrMsg(WSAGetLastError());
		return 0;
	}
	printf("Socket创建成功!\n");
	//绑定到端口28000
	sockaddr_in addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2800);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	int nBind = bind(g_sock, (sockaddr *)&addr, sizeof(addr));
	if(nBind != 0)
	{
		ErrMsg(WSAGetLastError());
		return 0;
	}
	//取得已绑定的端口号
	int nLen = sizeof(addr);
	getsockname(g_sock, (sockaddr *)&addr, &nLen);
	printf("Socket成功绑定到端口:%d,等待数据...\n", ntohs(addr.sin_port));
	//等待并接收信息
	sockaddr_in saClient = {0};
	int nFromLen = sizeof(saClient);
	char szBuff[256] = {0};
	recvfrom(g_sock, szBuff, 256, 0, (sockaddr *)&saClient, &nFromLen);
	printf("收到信息:‘%s’,从%s,%d\n", 
		szBuff, inet_ntoa(saClient.sin_addr), ntohs(saClient.sin_port));
	//向客户端发出回应
	strcpy(szBuff, "OK!");
	int nSent = sendto(g_sock, szBuff, strlen(szBuff) + 1, 0, (sockaddr *)&saClient, sizeof(saClient));
	if(nSent == 0)
		ErrMsg(WSAGetLastError());
	else
		printf("成功发出回应!\n");
	//关闭SOCKET
	closesocket(g_sock);
	//等待用户输入
	system("pause");
	//清理环境
	WSACleanup();
	return 0;
}

//取得错误详细情况,并输出
void ErrMsg(DWORD dwErr)
{
	char szErr[1024] = {0};
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 
		NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
		szErr, 1024, NULL);
	printf(szErr);
}
错误解决同客户端程序的解决方法

编译执行:

此时运行客户端程序,服务器端便可收到客户端发来的信息并作出回应:

客户端收到服务器端做出的回应:



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UDP协议是一种无连接传输协议,它不对数据传输进行可靠性保证,因此在进行数据传输时,可能会出现数据丢失、重复、乱序等问题。为了保证UDP数据传输的可靠性,需要使用一些技术手段进行处理,其中最常用的是使用UDP Socket实现可靠数据传输UDP Socket是在UDP协议基础上进行实现的一个套接字。UDP Socket可以通过设置一些参数和使用一些技术手段,来实现UDP数据传输的可靠性。下面就具体介绍UDP Socket实现可靠数据传输的原理。 1.数据分片 UDP Socket将数据分片传输,每个数据分片都包含一个序号,接收端可以通过序号来判断数据分片是否存在丢失、重复或者乱序等问题。如果数据分片存在以上问题,则可以进行相应的处理,从而保证数据传输的可靠性。 2.确认机制 UDP Socket采用确认机制来保证数据传输的可靠性。发送端在发送每个数据分片后,会等待接收端返回确认信息,确认信息包含接收到的数据的序号。如果接收端返回的确认信息与发送端发送的序号不一致,则说明数据分片存在丢失或者乱序问题,发送端需要重新发送该数据分片。 3.超时重传机制 UDP Socket采用超时重传机制来保证数据传输的可靠性。发送端在发送每个数据分片后,会设置一个超时时间,在超时时间内如果未收到接收端的确认信息,则发送端会重新发送该数据分片。通过这种方式,可以保证数据分片不会因为网络问题而丢失。 4.流量控制 UDP Socket采用流量控制来保证数据传输的可靠性。在数据传输的过程中,发送端需要根据接收端的处理能力来控制数据的发送速度,防止数据发送过快导致接收端无法及时处理。通过流量控制,可以避免数据丢失或者传输延迟过大的问题。 综上所述,UDP Socket实现可靠数据传输的原理主要包括数据分片、确认机制、超时重传机制和流量控制等方面。通过这些技术手段,可以保证UDP数据传输的可靠性,从而满足各种网络应用的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值