说明:
利用UDP协议,创建一个服务器和一个客户端。两者间进行通信。
由客户端进行输入内容,而服务器将接受的内容进行再一次返回,并显示在服务端。
// UDP_Seversock.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#pragma comment (lib,"WS2_32.lib") //服务器端
int _tmain(int argc, _TCHAR* argv[])
{
//检测版本
WSADATA wsaData;
int nErr = WSAStartup(MAKEWORD(, ), &wsaData);
if (nErr != )
{
printf("WSAStartup Failed %d", GetLastError());
return -;
} if (HIBYTE(wsaData.wVersion != || wsaData.wVersion != ))
{
printf("WinSock2 version not is WS2_32");
WSACleanup();
return -;
} //开始
SOCKET sockSever = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //设置端口号和IP地址,INADDR_ANY是任意IP地址
SOCKADDR_IN sockSeverAddr;
sockSeverAddr.sin_family = AF_INET;
sockSeverAddr.sin_port = htons();
//sockSeverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
sockSeverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //将socket进行绑定
int nBindErr = bind(sockSever, (sockaddr*)&sockSeverAddr, sizeof(SOCKADDR_IN));
if (nBindErr == SOCKET_ERROR)
{
printf("bind Error!");
closesocket(sockSever);
WSACleanup();
}
printf("connect sucess!\n"); SOCKADDR_IN SenderAddr;
int SenderAddrSize = sizeof (SenderAddr); char pRecvBuf[MAXBYTE] = { };
char pPrintBuf[MAXBYTE] = { }; while ()
{
int nResult = recvfrom(sockSever, pRecvBuf, MAXBYTE, , (SOCKADDR *)&SenderAddr, &SenderAddrSize); if (nResult == SOCKET_ERROR)
{
printf("recvfrom failed with error ");
} //重置,将IP地址和端口号,内容存放在pPrintBuf中
sprintf_s(pPrintBuf, "%s(%d):%s\n", inet_ntoa(sockSeverAddr.sin_addr), ntohs(sockSeverAddr.sin_port), pRecvBuf); //输出在窗口
printf("%s\n", pPrintBuf); //客户端请求退出
if (strcmp(pRecvBuf, "Q") == )
{
break;
} int nSendResult = sendto(sockSever, pRecvBuf, MAXBYTE, , (sockaddr*)&SenderAddr, SenderAddrSize);
if (nSendResult == SOCKET_ERROR)
{
printf("sendto Error!");
break;
}
} closesocket(sockSever);
WSACleanup();
return ;
}
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib,"WS2_32.lib") //客户端
int _tmain(int argc, _TCHAR* argv[])
{
//socket版本检测
WSAData wsaData;
int nErr=WSAStartup(MAKEWORD(, ), &wsaData);
if (nErr != )
{
printf("WSAStartup Failed %d", GetLastError());
return -;
}
if (HIBYTE(wsaData.wVersion) != || LOBYTE(wsaData.wVersion) != )
{
printf("WinSock2 version not is WS2_32");
WSACleanup();
return -;
} //程序开始
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //设定端口和IP地址,127.0.0.1是本机回环地址
SOCKADDR_IN sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons();
sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int RecvAddrSize = sizeof (SOCKADDR_IN); //int nBindErr=bind(sockClient, (sockaddr*)&sockAddr, sizeof(SOCKADDR_IN));
//if (nBindErr == SOCKET_ERROR)
//{
// printf("bind Error!");
// closesocket(sockClient);
// WSACleanup();
// return -1;
//} printf("connect sucess!\n"); char pSendBuf[MAXBYTE] = { }; //发送服务器的内容
char pRecvBuf[MAXBYTE] = { }; //接受服务器返回的内容 while ()
{
gets_s(pSendBuf); //发送给服务器
int nResule = sendto(sockClient, pSendBuf, MAXBYTE, , (SOCKADDR *)& sockAddr, RecvAddrSize);
if (nResule == SOCKET_ERROR)
{
printf("sendto Error!");
} //接受服务器返回的内容
int nRecvErr = recvfrom(sockClient, pRecvBuf, MAXBYTE, , (SOCKADDR *)& sockAddr, &RecvAddrSize);
if (nRecvErr == SOCKET_ERROR)
{
break;
} //服务器返回内容
printf("return from sever:%s\n", pRecvBuf); }
closesocket(sockClient);
WSACleanup();
return ;
}
注意点;
问题:为什么UDP协议的客户端的socket不需要绑定IP地址和端口号?
解析;
书上都是这么说的,UDP客户端不用绑定IP和端口,操作系统会给它自动分配端口。。。。
但是虽然没有显示绑定,但是操作系统却似乎做了些隐蔽的事情。
首先,在客户端,fd = socket(AF_INET, SOCK_DGRAM, 0),然后就想在此fd下进行recvfrom是收不到对方(假设对方就是服务器吧)的消息是办不到的,
其实想想也很容易明白,这是fd未和任何端口、IP产生关联要是这样都能收到消息,那真要乱套了。想要在没绑定的情况下受到服务器发来的消息,
首先客户端得通过fd描述符首先向服务器发信息,然后这时在fd下进行阻塞recvfrom就能收到消息了,如果再在客户端上fd 1= socket(AF_INET, SOCK_DGRAM, 0),
想在fd1 上进行recvfrom依然收不到消息,因为fd和服务器同过信,但fd1没有,所以fd1收不到,但是从fd1向服务器发消息没问题!所一总结一下就是,
只有当已通过fd向服务器发送了消息时(并且已经发通了),才能在fd处收到服务器发回来的消息,但是向服务器发送消息就不需要。
所以说操作系统在此做了些隐蔽的事情,当fd首先向服务器发消息时客户端自动选折IP和一个PORT与该fd关联了起来,(我觉得相当于背后还是绑定了一样)。
而后面创建的fd1和之前的fd他们出客户端的PORT是不同的(我在服务器端检测了一下),所以通过fd向服务器发了消息但想在新建立的fd1下去recvfrom收不到消息。
另外,只能对一个socket描述符绑定一次,不能绑定多次,除非前面已经将该描述符close了。
反过来一个端口也只能被绑定到同一个socket描述符上,除非他们使用的不同的协议。
注意:如果客户端绑定了,那么在服务器端将无法输出任何东西,在recvfrom()该函数阻塞。
1.每一次都要进行版本检测。
2.头文件的包含,#include <WinSock2.h>一定要在#include <Windows.h>的前面。
如:
#include <WinSock2.h>
#include <Windows.h>
C/S模型之UDP协议的更多相关文章
-
python 全栈开发,Day33(tcp协议和udp协议,互联网协议与osi模型,socket概念,套接字(socket)初使用)
先来回顾一下昨天的内容 网络编程开发架构 B/S C/S架构网卡 mac地址网段 ip地址 : 表示了一台电脑在网络中的位置 子网掩码 : ip和子网掩码按位与得到网段 网关ip : 内置在路由器中的 ...
-
(1)基于tcp协议的编程模型 (2)tcp协议和udp协议的比较 (3)基于udp协议的编程模型 (4)反射机制
1.基于tcp协议的编程模型(重中之重)1.1 编程模型服务器: (1)创建ServerSocket类型的对象,并提供端口号: (2)等待客户端的连接请求,调用accept()方法: (3)使用输入输 ...
-
(1)网络编程的常识 (2)基于tcp协议的编程模型 (3)tcp协议和udp协议的比较 (4)基于udp协议的编程模型
1.网络编程的常识 目前主流的网络通讯软件有:微信.QQ.YY.陌陌.探探.飞信.阿里旺旺.... 在吗? 1.1 七层网络模型(熟悉) 为了保证数据传递的可靠安全等等,ISO(国际标准委员会组织)将 ...
-
UDP协议----简单的CS模型实现
UDP简单介绍 传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议.TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输.但UDP也是网络通信中不可或缺 ...
-
OSI模型第四层传输层--UDP协议
1.udp协议 UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成[2] ,提供面向事务的简单不可靠信息传送服务.UDP 协议 ...
-
UDP协议开发
UDP是用户数据报协议(User Datagram Protocol,UDP)的简称,其主要作用是将网络数据流量压缩成数据报形式,提供面向事务的简单信息传送服务.与TCP协议不同,UDP协议直接利用I ...
-
网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
-
UDP协议疑难杂症全景解析
转载:http://blog.csdn.net/dog250/article/details/6896949 UDP协议疑难杂症全景解析 2011-10-22 19:26 2989人阅读 评论(4) ...
-
OSI七层模型对应的协议
osi七层模型对应的协议 author:headsen chen 2017-10-21 11:44:47 个人原创,转载请注明作者,出处.否则依法追究法律责任 1,物理层:带信号的,同轴电缆, ...
随机推荐
-
SOA相关资料整理分享
昨@幸福框架同学问能否推荐SOA一些资,.想想之前看过不少资料文档,就整理分享下,有需要的可以参考下. 文章链接 理解面向服务的体系结构中企业服务总线场景和解决方案,第 1 部分 SOA 和 web ...
-
paip.日志中文编码原理问题本质解决python
paip.日志中文编码原理问题本质解决python 默认的python日志编码仅仅gbk...保存utf8字符错误..输出到个eric5的控制台十默认好像十unicode的,要是有没显示出来的字符,大 ...
-
pl/sql programming 03 语言基础
PL/SQL 块结构 最小的有意义的代码单元叫做 块(block). 一个块是一组代码, 这个块给出了执行边界, 也为变量声明和异常处理提供了作用范围, pl/sql 准许我们创建匿名块和命名块, 命 ...
-
clientTop、clientWidth、offsetTop、offsetWidth、scrollTop
<div id="drag" class="drag">drag me</div> <script type="text ...
-
如何解决PHP生成UTF-8编码的CSV文件用Excel打开乱码的问题
为了识别 Unicode 文件,Microsoft 建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE字符开头.这作为一个”特征符”或”字节顺序标记(byte-o ...
-
unix 环境高级编程-读书笔记与习题解答-第二篇
第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...
-
使用PHPExcel导入导出excel格式文件
使用PHPExcel导入导出excel格式文件 作者:zccst 因为导出使用较多,以下是导出实现过程. 第一步,将PHPExcel的源码拷贝到项目的lib下 文件包含:PHPExcel.ph ...
-
loadrunner11的移动端性能测试之脚本录制
以前使用LR11录制过一个app的登录操作,这里记录一下 测试准备 硬件要求 1, 负载测试机一台(内存8G以上,cpu 1.5GHZ以上,存储空间20G以上)或两台以上(控制机和多个负载机). 2 ...
-
怎么给PDF去除页眉页脚
PDF文件我们现在都会使用到,但有时需编辑PDF文件的时候,小伙伴们都知道该怎么操作吗,不知道的小伙伴不用担心,今天小编就来跟大家分享一下怎么删除PDF文件的页眉页脚,我们一起来看看下面的文章吧 操作 ...
-
转载:第2章 Nginx的配置 概述《深入理解Nginx》(陶辉)
原文:https://book.2cto.com/201304/19623.html Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能.使用这些模块 ...