用Socket
实现UDP 协议下的网络通信
王伟,蓝雯飞,高伟华
(中南民族大学计算机学院,湖北武汉430070)
摘要:随着计算机技术、网络技术、通信技术的迅速发展,越来越多的网络信息走入了大众的生活,对网络信息的
传输设计和实现技术要求也越来越高。研究了基于VC 的UDP 网络编程的设计与实现,并采用同步传输技术实现了
一个简单的UDP
Server。
关键词:网络编程;UDP;同步传输
中图分类号:TP393.04 文献标识码:A 文章编号:1672-7800(2009)09-0115-03
1 网络通信技术
计算机网络将多个具有独立工作能力的计算机系统通过
通信设备和线路由功能完善的网络软件实现资源共享和数据
通信的系统。
1.1 网络的分类
用于计算机网络分类的标准很多,如拓扑结构,应用协议
等。但是这些标准只能反映网络某方面的特征,最能反映网络
技术本质特征的分类标准是分布距离,按分布距离分为LAN,
MAN,WAN,INTERNET。
1.2 网络通信协议
网络通信协议是通信双方在通信时遵循的规则和约定,是
信息网络中使用的通信语言。它有3 个要素:语法,即信息格
式;语义,某些信息组合的含义;同步,即收、发双方能分辨出通
信的开始和结束。在计算机网络中用协议数据单元PDU 描述
通信协议,PDU 由控制部分和数据部分组成,控制部分由若干
字段组成,表示通信中用到的协议。当今局域网中最常见的三
个协议是MICROSOFT
的NETBEUI、NOVELL 的IPX/SPX 和交
叉平台TCP/IP。
1.3 网络通信的同步与异步
同步就是发送和接受数据的双方保持步调一致,发送数据
方发送数据后,必须等到接受数据方发回了接受到了数据的信
息后,才能做下面的事情。而作为接收数据方,在决定接收后,
必须接收到数据后才能做下面的事情,它需要不断地轮询接收
缓冲区有没有数据,又称为阻塞方式。异步则是在发送和接收
数据时还可以做其它的事情,又称为非阻塞方式。
2 Socket 基本原理
在Windows
网络编程中, 套接字接口主要有3 种类型:流
式套接字,数据报套接字以及原始套接字、流式套接字定义了
一种面向连接的服务, 实现了无差错无重复的顺序数据传输,
无长度限制。数据报套接字接口定义了一种无连接的服务,数
据通过相互独立的报文进行传输,是无序的,并且不保证可靠。
原始套接字允许对低层协议IP 或ICMP 直接访问, 主要应用
网络协议的测试。在现在的网络应用中,通信双方最常见的交
互模式便是Client/Server
模式。客户/服务器模式通常采用监
听/连接的方式实现。服务器端应用程序在一个端口监听对服
务的请求,也就是说,服务进程一直处于休眠状态,直到有一个
客户对这个服务提出了连接请求,此时服务线程被“唤醒”并为
客户提供服务,即对客户的请求做出适当的反应。采用面向连
接的协议(如TCP)时,服务器处理的请求比较复杂,并不是简
单的请求应答所能解决的, 而且大多数TCP 服务器是并发服
务器,因此需要经过反复的交互。使用面向连接的协议时,典型
的套接字接口调用流程如图1 所示。
图1 典型的套接字接口调用流程
软件导刊
Software Guide
第8卷%第9期
2009年9 月
Vol.8
No.9
Sep.
2009
软件导刊2009 年
3 基于UDP 的Socket 编程技术
UDP 是一种面向非连接,不可靠的通讯协议,相对于TCP
来说,虽然可靠性不及,但传输效率较高。所以在网络上仍有很
大的用途。
server 端:open a
socket (socket)-->name thesocket(bind)
-->send and receive data(sendto recvfrom)-->close socket(closesocket)
client 端:open a
socket (socket) -->send
and receivedata
(sendto
recvfrom)-->close
socket(closesocket)
server 端无需listen,client 端无需connect, 因此UDP 中
server 和client
的区别相对较模糊。只要调用sendto 和recvfrom
就可以给指定的地址收发数据,但并不保证收发的数据的完整
性和可靠性。
4 如何开发一个Server-Client
模型的程序
开发原理:服务器,使用ServerSocket
监听指定的端口,端
口可以随意指定(由于1024 以下的端口通常属于保留端口,在
一些操作系统中不可以随意使用, 所以建议使用大于1024 的
端口),等待客户连接请求,客户连接后,会话产生,在完成会话
后,关闭连接。客户端,使用Socket 对网络上某一个服务器的
某一个端口发出连接请求,一旦连接成功,打开会话,会话完成
后,关闭Socket。客户端不需要指定打开的端口,通常临时的、
动态的分配一个1024 以上的端口。
(1)服务器端编程步骤①引入头文件Include “Winsock2.
h”;②加载套接字库使用函数WSAStartup (); ③创建套接字
库,成功的话,返回一个Socket
函数Socket();④绑定套接字
库,使其绑定到一个IP 和一个端口上函数:Bind();⑤接收数
据。函数:Accept();⑥程序结束时关闭套接字CloseSocket()/
WSAcleanup()。
(2)客户端的实现过程:①创建一个套接字,函数Socket
();②向服务器发送数据函数:Sendto();③关闭套接字。
5 程序实现详细过程
为简便起见,程序用一个控制台程序实现。服务端和客户
端分别用两个类实现。
在服务器端的类中,定义两个函数CreateSocket()和On-
Received()用于建立和绑定Socket
和从客户端接受数据。
代码分别如下:
void Server:CreateSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested=MAKEWORD(1,1);
err=WSAStartup(wVersionRequested,&wsaData);
if(err !
=0)
{
return;
}
if (LOBYTE
(wsaData.wVersion)! =1 ||HIBYTE (wsaData.
wVersion)! =1)
{
WSACleanup();
return;
}
sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(8889);
if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==
SOCKET_ERROR)
{
printf("bind failed! ");
return;
}
}
void Server::OnReceived()
{
char recvBuf[50];
SOCKADDR_IN addrClient;
addrClient.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrClient.sin_family=AF_INET;
addrClient.sin_port=htons(8889);
int len=sizeof(SOCKADDR);
recvfrom (sockSrv,recvBuf,50,0, (SOCKADDR*)&addr-
Client,&len);
printf("%s\n",recvBuf);
}
在客户端的类中, 我将Socket 创建的类写在了构造函数
中,然后再定义一个SendMsg()函数,用于向服务器端发送数
据。
具体代码如下:
CClient::CClient()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!
=0)
{
return;
· 116 ·
第9 期
}
if (LOBYTE
(wsaData.wVersion)! =2 ||HIBYTE (wsaData.
wVersion)! =2)
{
WSACleanup();
return;
}
sockClient=socket(AF_INET,SOCK_DGRAM,0);
}
void CClient:SendMsg(char *sz)
{
SOCKADDR_IN addrClient;
addrClient.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrClient.sin_family=AF_INET;
addrClient.sin_port=htons(8889);
sendto (sockClient,sz,3,0, (SOCKADDR*)&addrClient,
sizeof(SOCKADDR));
}
最后, 在主函数中分别定义一个服务器和客户端的类对
象,以启动和关闭服务器。
具体代码如下:
int_tmain(int argc,TCHAR* argv[],TCHAR* envp[])
{
char szBuf[100];
Server pServer;
cout<<"UDP Demo:"<
pServer.CreateSocket();
CClient pClient;
while(1)
{
memset(szBuf,0,100);
cout<<"Input:";
cin>>szBuf;
if(strcmp(szBuf,"quit")==0)
{
pServer.~Server();
break;
}
pClient.SendMsg(szBuf);
pServer.OnReceived();
}
return 0;
}
6 结束语
论文讨论了基于UDP 的Socket 编程,如__________何开发一个Server-
Client 模型的程序,服务端编程的步骤、客户端编程的步骤、
封装等完整的编程流程, 对UDP 异步传输进行了详细的系统
分析和设计, 针对UDP 异步传输本身的特点和对系统的功能
要求,选用一个简单UDPServer 实现的系统实现。这对于我们
今后UDP 的开发和实现具有很好的指导作用。
参考文献:
[1] 范辉.Visual C++程序设计简明教程[M].北京:高等教育出版社,
2001.
[2] 谭浩强.C 程序设计[M].北京:清华大学出版社,1999.
[3] Jeffrey
Richter.Windows 核心编程[M]. 北京: 机械工业出版社,
2000.
[4] 李彦,李伟明.Visual
C++项目开发全程实录[M].北京:清华大学
出版社,2008.
(责任编辑:周晓辉)
王伟,蓝雯飞,高伟华:用Socket 实现UDP 协议下的网络通信
Internetwork Communication Based on UDP Protocol by Using
Socket
Abstract:As using computer technology, network technology,
communication technology widely, more and more network information is involved
people’s life, meanwhile, the request of communication design
and implementation technique is higher and higher. Reaching UDP
network programming based on VC, and realizing a simple
UDP server by using synchronous transmission.
Key Words:Network Programming; UDP; Synchronous Transmission
·117·
阅读(8636) | 评论(0) | 转发(0) |