说明:
利用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协议的更多相关文章

  1. python 全栈开发,Day33(tcp协议和udp协议,互联网协议与osi模型,socket概念,套接字(socket)初使用)

    先来回顾一下昨天的内容 网络编程开发架构 B/S C/S架构网卡 mac地址网段 ip地址 : 表示了一台电脑在网络中的位置 子网掩码 : ip和子网掩码按位与得到网段 网关ip : 内置在路由器中的 ...

  2. (1)基于tcp协议的编程模型 (2)tcp协议和udp协议的比较 (3)基于udp协议的编程模型 (4)反射机制

    1.基于tcp协议的编程模型(重中之重)1.1 编程模型服务器: (1)创建ServerSocket类型的对象,并提供端口号: (2)等待客户端的连接请求,调用accept()方法: (3)使用输入输 ...

  3. (1)网络编程的常识 (2)基于tcp协议的编程模型 (3)tcp协议和udp协议的比较 (4)基于udp协议的编程模型

    1.网络编程的常识 目前主流的网络通讯软件有:微信.QQ.YY.陌陌.探探.飞信.阿里旺旺.... 在吗? 1.1 七层网络模型(熟悉) 为了保证数据传递的可靠安全等等,ISO(国际标准委员会组织)将 ...

  4. UDP协议----简单的CS模型实现

    UDP简单介绍 传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议.TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输.但UDP也是网络通信中不可或缺 ...

  5. OSI模型第四层传输层--UDP协议

    1.udp协议 UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成[2]  ,提供面向事务的简单不可靠信息传送服务.UDP 协议 ...

  6. UDP协议开发

    UDP是用户数据报协议(User Datagram Protocol,UDP)的简称,其主要作用是将网络数据流量压缩成数据报形式,提供面向事务的简单信息传送服务.与TCP协议不同,UDP协议直接利用I ...

  7. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  8. UDP协议疑难杂症全景解析

    转载:http://blog.csdn.net/dog250/article/details/6896949 UDP协议疑难杂症全景解析 2011-10-22 19:26 2989人阅读 评论(4)  ...

  9. OSI七层模型对应的协议

    osi七层模型对应的协议 author:headsen chen    2017-10-21  11:44:47 个人原创,转载请注明作者,出处.否则依法追究法律责任 1,物理层:带信号的,同轴电缆, ...

随机推荐

  1. Android电话拨号器_06

    在Android模拟器中开发时,有时需要模拟拨打电话功能,由于模拟器不能直接当做真机使用,所以我们需要再模拟器中模拟真机拨打电话,首先需要创建两个模拟器,当做两部Android手机来使用.由于Andr ...

  2. 【CF886D】Restoration of string 乱搞

    [CF886D]Restoration of string 题意:对于给定的一个母串,定义一个字符串是出现频率最多的,当且仅当它在母串中出现的次数最多(可以有多个出现次数最多的,出现的位置可以重叠). ...

  3. RSA加密工具类(非对称加密算法)

    import com.jfinal.log.Log;import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; ...

  4. mysql 外键 cascade

    1 . cascade方式在父表上update/delete记录时,同步update/delete掉子表的匹配记录 2. set null方式在父表上update/delete记录时,将子表上匹配记录 ...

  5. Nginx配置项优化详解(转)

    (1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...

  6. 被included或者被required的文件都来自哪里呢

    过PHP,你可以使用不同函数帮助你重用代码.具体用到的函数取决于你打算重用的内容. 主函数如下: * include() and include_once() * require() and requ ...

  7. mongodb的学习笔记一(集合和文档的增删改查)

    1数据库的增删改查 一.增加一个数据库: use blog-----切换到指定的数据库,如果数据库不存在,则自动创建该数据库(新建的数据库,如果没有存储对应的集合,是不会显示出来的) 二.删除一个数据 ...

  8. Centos清除IP

    要把配置好的ip清除掉,可以使用以下命令: ip addr flush dev eth0 如果系统中没有ip这个命令,可以使用更简单的: ifconfig eth0 0.0.0.0 可以用于PPTP拨 ...

  9. poj3252Round Numbers【组合数】【数位dp】

    Round Numbers The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, ...

  10. 【转】.NET Framework、C#语言、IDE、CLR 版本历史及其差异

    原文地址: http://www.cnblogs.com/PurpleCow/archive/2012/06/17/2552780.html http://www.cnblogs.com/lhking ...