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
与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
相关文章推荐