您的位置:首页 > 其它

Win32 UDP Socket通信学习

2015-06-18 16:25 274 查看
学习内容,参见《Windows网络编程》第7章 Winsock基础

与TCP流式协议不同,UDP为数据报协议。

服务端接受数据,客户端发送数据。

UDP服务端流程

Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
bind绑定到IP地址和端口。
recvfrom/WSARecvFrom接受数据。

UDP客户端流程

UDP客户端有两种方式,一种为无连接,一种为创建虚拟连接。

方式一 无连接

Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
设置服务器地址和端口。
sento/WSASendTo发送数据。

方式二 建立虚拟连接

Socket或WSASocket建立套接字,用SOCK_DGRAM标志。
设置服务器地址和端口。
connect连接服务端。
调用send发送数据。

使用windows的Winsock 2编程,需要进行工程配置。

工程右键Properties->ConfigurationProperties->Linker->Input->Additional Dependencies中添加ws2_32.lib。
Demo代码采用Multi-Byte方式,设置Properties->ConfigurationProperties->General->Character Set为Use Multi-Byte Character Set。

备注:所有关系到收发数据的缓冲都属于简单的char类型,这些函数没有Unicode版本。当字符集为Unicode时,需要进行字符串转换。

服务端源码,UDPServer.cpp。

[cpp] view
plaincopy

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

//

#include "stdafx.h"

#include <WinSock2.h>

#include <stdio.h>

#include <stdlib.h>

#define DEFAULT_PORT 5150

#define DEFAULT_COUNT 5

#define DEFAULT_BUFFER_LENGTH 4096

int iPort = DEFAULT_PORT;

DWORD dwCount = DEFAULT_COUNT;

DWORD dwLength = DEFAULT_BUFFER_LENGTH;

BOOL bInterface = FALSE;

char szIterface[32];

//Print usage information and exit

void usage()

{

printf("usage:sender[-p:int][-i:IP][-n:x][-b:x]\n\n");

printf(" -p:int Local port\n");

printf(" -i:IP Local IP address to listen on\n");

printf(" -n:x Number of times to send message\n");

printf(" -b:x Size of buffer to send \n\n");

ExitProcess(1);

}

//ValidateArgs

void ValidateArgs(int argc, _TCHAR** argv)

{

for (int i = 1; i < argc; i++)

{

if ((argv[i][0] == _T('-') || (argv[i][0] == _T('/'))))

{

switch (tolower(argv[i][1]))

{

case _T('p'):

if (_tcslen(argv[i]) > 3)

{

iPort = _ttoi(&argv[i][3]);

}

break;

case _T('n'):

//Number of times to receive message

if (_tcslen(argv[i]) > 3)

{

dwCount = _ttol(&argv[i][3]);

}

break;

case _T('b'):

//Buffer size

if (_tcslen(argv[i]) > 3)

{

dwLength = _ttol(&argv[i][3]);

}

break;

case _T('i'):

//Interface to receive datagrams on

if (_tcslen(argv[i]) > 3)

{

bInterface = TRUE;

_tcscpy_s(szIterface, &argv[i][3]);

}

break;

default:

usage();

break;

}

}

}

}

int _tmain(int argc, _TCHAR* argv[])

{

//Parse arguments and load winsock

ValidateArgs(argc, argv);

WSADATA wsd;

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)

{

printf("WSAStartup failed!\n");

return 1;

}

//Create the socket, and bind it to a local interface and port

SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

if (s == INVALID_SOCKET)

{

printf("socket() failed:%d\n", WSAGetLastError());

return 1;

}

SOCKADDR_IN local;

local.sin_family = AF_INET;

local.sin_port = htons((short)iPort);

if (bInterface)

{

local.sin_addr.s_addr = inet_addr(szIterface);

}

else

{

local.sin_addr.s_addr = htonl(INADDR_ANY);

}

if (bind(s, (SOCKADDR*)&local, sizeof(local)) == SOCKET_ERROR)

{

printf("bind() failed:%d\n", WSAGetLastError());

return 1;

}

//Allocate the receive buffer

char* recvbuf = (char*)GlobalAlloc(GMEM_FIXED, dwLength);

if (!recvbuf)

{

printf("GlobalAlloc() failed:%d\n", GetLastError());

return 1;

}

//Read the datagrams

SOCKADDR_IN sender;

for (int i = 0; i < (int)dwCount; i++)

{

int nSenderSize = sizeof(sender);

int ret = recvfrom(s, recvbuf, dwLength, 0,

(SOCKADDR*)&sender, &nSenderSize);

if (ret == SOCKET_ERROR)

{

printf("recvfrom() failed:%d\n", WSAGetLastError());

break;

}

else if (ret == 0)

{

break;

}

else

{

recvbuf[ret] = _T('\0');

printf("[%s] sent me:'%s'\n",

inet_ntoa(sender.sin_addr), recvbuf);

}

}

closesocket(s);

GlobalFree(recvbuf);

WSACleanup();

return 0;

}

客户端源码,UDPClient.cpp。

[cpp] view
plaincopy

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

//

#include "stdafx.h"

#include <WinSock2.h>

#include <stdio.h>

#include <stdlib.h>

#define DEFAULT_PORT 5150

#define DEFAULT_COUNT 25

#define DEFAULT_CHAR 'a'

#define DEFAULT_BUFFER_LENGTH 32

BOOL bConnect = FALSE;

int iPort = DEFAULT_PORT;

char cChar = DEFAULT_CHAR;

DWORD dwCount = DEFAULT_COUNT;

DWORD dwLength = DEFAULT_BUFFER_LENGTH;

char szRecipient[128];

//Print usage information and exit

void usage()

{

printf("usage:sender[-p:int][-r:IP][-c][-n:x][-b:x][-d:c]\n\n");

printf(" -p:int Remote port\n");

printf(" -r:IP Recipient's IP address or host name\n");

printf(" -c Connect to remote IP first\n");

printf(" -n:x Number of times to send message\n");

printf(" -b:x Size of buffer to send\n");

printf(" -d:c Character to fill buffer with\n\n");

ExitProcess(1);

}

//Parse the command line arguments, and set some global flags to

//indicate what actions to perform

void ValidateArgs(int argc, _TCHAR** argv)

{

for (int i = 1; i < argc; i++)

{

if ((argv[i][0] == _T('-') || (argv[i][0] == _T('/'))))

{

switch (tolower(argv[i][1]))

{

case _T('p'):

//Remote port

if (_tcslen(argv[i]) > 3)

{

iPort = _ttoi(&argv[i][3]);

}

break;

case _T('r'):

//Recipient's IP addr

if (_tcslen(argv[i]) > 3)

{

_tcscpy_s(szRecipient, &argv[i][3]);

}

break;

case _T('c'):

//Connect to recipient's IP addr

bConnect = TRUE;

break;

case _T('n'):

if (_tcslen(argv[i]) > 3)

{

dwCount = _ttol(&argv[i][3]);

}

break;

case _T('b'):

if (_tcslen(argv[i]) > 3)

{

dwLength = _ttol(&argv[i][3]);

}

break;

case _T('d'):

cChar = argv[i][3];

break;

default:

usage();

break;

}

}

}

}

int _tmain(int argc, _TCHAR* argv[])

{

ValidateArgs(argc, argv);

WSADATA wsd;

if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)

{

printf("WSAStartup failed!\n");

return 1;

}

//Crate the socket

SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

if (s == INVALID_SOCKET)

{

printf("socket() failed:%d\n", WSAGetLastError());

return 1;

}

//Resolve the recipient's IP address or host name

SOCKADDR_IN recipient;

recipient.sin_family = AF_INET;

recipient.sin_port = htons((short)iPort);

int nServerLen = (int)_tcslen(szRecipient);

if (0 == nServerLen)

{

struct hostent* host = gethostbyname(szRecipient);

if (host == NULL)

{

printf("gethostbyname() failed:%d\n", WSAGetLastError());

WSACleanup();

return 1;

}

CopyMemory(&recipient.sin_addr, host->h_addr_list[0], host->h_length);

}

else

{

recipient.sin_addr.s_addr = inet_addr(szRecipient);

}

//Allocate the send buffer

char* sendbuf = (char*)GlobalAlloc(GMEM_FIXED, dwLength);

if (!sendbuf)

{

printf("GlobalAlloc() failed:%d\n", GetLastError());

return 1;

}

memset(sendbuf, cChar, dwLength);

if (bConnect)

{

//If the connect option is set, "connect" to the recipient

//and send the data with the send() fuction

if (connect(s, (SOCKADDR*)&recipient,

sizeof(recipient)) == SOCKET_ERROR)

{

printf("connect() failed:%d\n", WSAGetLastError());

GlobalFree(sendbuf);

WSACleanup();

return 1;

}

for (int i = 0; i < (int)dwCount; i++)

{

int ret = send(s, sendbuf, dwLength, 0);

if (ret == SOCKET_ERROR)

{

printf("send() failed:%d\n", WSAGetLastError());

break;

}

else if (ret == 0)

{

break;

}

}

}

else

{

//Otherwise, use the sendto() function

for (int i = 0; i < (int)dwCount; i++)

{

int ret = sendto(s, sendbuf, dwLength, 0,

(SOCKADDR*)&recipient, sizeof(recipient));

if (ret == SOCKET_ERROR)

{

printf("send() failed:%d\n", WSAGetLastError());

break;

}

else if (ret == 0)

{

break;

}

}

}

closesocket(s);

GlobalFree(sendbuf);

WSACleanup();

return 0;

}

/article/8355155.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: