C++ Winsock网络编程(3)——UDP实现

        UDP是一种不可靠的传输协议,使用UDP通讯的双方,服务器不需要监听、等待客户端连接,客户端也不需要连接服务器后再发送消息,双方使用recvfrom()函数和sendto()函数收发消息,这两个函数的原型如下:

int recvfrom(
  _In_         SOCKET s,
  _Out_        char *buf,
  _In_         int len,
  _In_         int flags,
  _Out_        struct sockaddr *from,
  _Inout_opt_  int *fromlen
);

Parameters

s [in]

A descriptoridentifying a bound socket.

buf [out]

A buffer for theincoming data.

len [in]

The length, in bytes,of the buffer pointed to by the buf parameter.

flags [in]

A set of options thatmodify the behavior of the function call beyond the options specified for theassociated socket. See the Remarks below for more details.

from [out]

An optional pointerto a buffer in a sockaddr structurethat will hold the source address upon return.

fromlen [in, out, optional]

An optional pointerto the size, in bytes, of the buffer pointed to by the from parameter.

int sendto(
  _In_  SOCKET s,
  _In_  const char *buf,
  _In_  int len,
  _In_  int flags,
  _In_  const struct sockaddr *to,
  _In_  int tolen
);

Parameters

s [in]

A descriptoridentifying a (possibly connected) socket.

buf [in]

A pointer to a buffercontaining the data to be transmitted.

len [in]

The length, in bytes,of the data pointed to by the buf parameter.

flags [in]

A set of flags thatspecify the way in which the call is made.

to [in]

An optional pointerto a sockaddr structurethat contains the address of the target socket.

tolen [in]

The size, in bytes,of the address pointed to by the to parameter.

 

        下面通过一个例子来说明具体的通信过程。

服务器端代码:

// UDPServer.cpp : Defines the entry point for the console application.

#pragma comment (lib,"ws2_32.lib")

#include <Winsock2.h>
#include <iostream>

using namespace std;

void main()
{
	//版本协商
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 1, 1 );
	err = WSAStartup( wVersionRequested, &wsaData );

	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return;
	}

	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */

	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return; 
	}

	/* The WinSock DLL is acceptable. Proceed. */
	//创建数据报套接字
	SOCKET svr = socket(AF_INET,SOCK_DGRAM,0);

	//创建本地地址信息
	SOCKADDR_IN addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6000);
	addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	int len = sizeof(sockaddr);

	bind(svr,(sockaddr*)&addr,len);

	//创建客户端地址对象
	SOCKADDR_IN addrClient;
	char recvBuf[128];
	char sendBuf[128];
	char tempBuf[256];

	while(true)
	{
		//接收数据
		recvfrom(svr,recvBuf,128,0,(sockaddr*)&addrClient,&len);

		//将一个以网络字节顺序排列的IP地址转换为一个字符串IP地址
		char* ipClient = inet_ntoa(addrClient.sin_addr);
		cout<<ipClient<<" said:"<<recvBuf<<endl;
		cin>>sendBuf;

		//发送数据
		sendto(svr,sendBuf,strlen(sendBuf)+1,0,(sockaddr*)&addrClient,len);
	}

	closesocket(svr);
	WSACleanup();
}

客户端代码:

// UDPClient.cpp : Defines the entry point for the console application.

#pragma comment (lib,"ws2_32.lib")

#include <Winsock2.h>
#include <iostream>

using namespace std;

void main()

{

	//版本协商
	WORD wVersionRequested;
	WSADATA wsaData;

	int err;

	wVersionRequested = MAKEWORD( 1, 1 );
	err = WSAStartup( wVersionRequested, &wsaData );

	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return;
	}

	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */

	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return; 
	}

	/* The WinSock DLL is acceptable. Proceed. */
	//创建服务器套接字
	SOCKET Svr = socket(AF_INET,SOCK_DGRAM,0);
	//创建地址
	SOCKADDR_IN addrSvr;
	addrSvr.sin_family = AF_INET;
	addrSvr.sin_port = htons(6000);
	addrSvr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	char recvBuf[128];
	char sendBuf[128];

	int len = sizeof(sockaddr);

	while(true)
	{
		//gets_s(sendBuf);
		cin>>sendBuf;

		//发送数据
		sendto(Svr,sendBuf,strlen(sendBuf)+1,0,(sockaddr*)&addrSvr,len);
		
		//接收数据
		recvfrom(Svr,recvBuf,128,0,(sockaddr*)&addrSvr,&len);

		//将一个以网络字节顺序排列的IP地址转换为一个字符串IP地址
		char* ipSvr = inet_ntoa(addrSvr.sin_addr);
		//printf("%s said: %s/n",ipSvr,recvBuf);
		cout<<ipSvr<<" said:"<<recvBuf<<endl;
	}

	closesocket(Svr);
	WSACleanup();
}

参考:

http://blog.csdn.net/nyzhl/article/details/2612848

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740120(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/d


你可能感兴趣的:(C++,socket,网络编程,UDP,winsock)