C/S模型之UDP协议

说明:
利用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,物理层:带信号的,同轴电缆, ...
随机推荐
- Android电话拨号器_06
在Android模拟器中开发时,有时需要模拟拨打电话功能,由于模拟器不能直接当做真机使用,所以我们需要再模拟器中模拟真机拨打电话,首先需要创建两个模拟器,当做两部Android手机来使用.由于Andr ...
- 【CF886D】Restoration of string 乱搞
[CF886D]Restoration of string 题意:对于给定的一个母串,定义一个字符串是出现频率最多的,当且仅当它在母串中出现的次数最多(可以有多个出现次数最多的,出现的位置可以重叠). ...
- RSA加密工具类(非对称加密算法)
import com.jfinal.log.Log;import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; ...
- mysql 外键 cascade
1 . cascade方式在父表上update/delete记录时,同步update/delete掉子表的匹配记录 2. set null方式在父表上update/delete记录时,将子表上匹配记录 ...
- Nginx配置项优化详解(转)
(1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...
- 被included或者被required的文件都来自哪里呢
过PHP,你可以使用不同函数帮助你重用代码.具体用到的函数取决于你打算重用的内容. 主函数如下: * include() and include_once() * require() and requ ...
- mongodb的学习笔记一(集合和文档的增删改查)
1数据库的增删改查 一.增加一个数据库: use blog-----切换到指定的数据库,如果数据库不存在,则自动创建该数据库(新建的数据库,如果没有存储对应的集合,是不会显示出来的) 二.删除一个数据 ...
- Centos清除IP
要把配置好的ip清除掉,可以使用以下命令: ip addr flush dev eth0 如果系统中没有ip这个命令,可以使用更简单的: ifconfig eth0 0.0.0.0 可以用于PPTP拨 ...
- poj3252Round Numbers【组合数】【数位dp】
Round Numbers The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, ...
- 【转】.NET Framework、C#语言、IDE、CLR 版本历史及其差异
原文地址: http://www.cnblogs.com/PurpleCow/archive/2012/06/17/2552780.html http://www.cnblogs.com/lhking ...