前言
在Win32 中发送基础网络数据相比起其他语言如java可能比较复杂。
大致流程:
- 导入
Ws2_32.lib - 根据一定规范初始化
Ws2_32.lib - 创建套接字对象,用于指定协议类型
- 绑定套接字所指定的端口
- 调用收发函数
- 资源回收
有两种方式指示导入动态库
- 编译宏指示连接器
#pragma comment(lib,"Ws2_32.lib")
VS 中配置
WSAStartup 文档
这里我们直接抄官方文档代码即可
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
WSACleanup();
}
SOCKET sockServer = socket(
AF_INET,
SOCK_DGRAM,
IPPROTO_UDP
);
if (sockServer == INVALID_SOCKET)
{
printf("创建socket失败 \r\n");
return 0;
}
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(0x5566);
si.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int nRet = bind(
sockServer,
(sockaddr *)&si,
sizeof(si)
);
if (nRet == SOCKET_ERROR)
{
printf("绑定端口失败\r\n");
WSACleanup();
return 0;
}
(5). 调用收发函数 和 (6) 资源回收
/接收数据
sockaddr_in siRecf;
char aryBuf[MAXBYTE] = { 0 };
int nNameLen = sizeof(siRecf);
while (true)
{
nRet = recvfrom(
sockServer,
aryBuf,
sizeof(aryBuf),
0,
(sockaddr *)&siRecf,
&nNameLen
);
if (nRet == SOCKET_ERROR)
{
printf("接收信息错误\r\n");
WSACleanup();
return 0;
}
std::cout << "收到客户端信息:" << aryBuf << std::endl;
char aryBuf[MAXBYTE] = { "hello Server" };
printf("请输入要发送的数据\r\n");
std::cin >> aryBuf;
nRet = sendto(sockServer, aryBuf, sizeof(aryBuf), 0, (sockaddr *)&siRecf, sizeof(siRecf));
if (nRet == SOCKET_ERROR)
{
printf("发送数据错误 \r\n");
WSACleanup();
return 0;
}
}
closesocket(sockServer);
WSACleanup();
return 0;
我们看下完整服务器的完整代码:
#include <iostream>
#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
SOCKET sockServer = socket(
AF_INET,
SOCK_DGRAM,
IPPROTO_UDP
);
if (sockServer == INVALID_SOCKET)
{
printf("创建socket失败 \r\n");
return 0;
}
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(0x5566);
si.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int nRet = bind(
sockServer,
(sockaddr *)&si,
sizeof(si)
);
if (nRet == SOCKET_ERROR)
{
printf("绑定端口失败\r\n");
WSACleanup();
return 0;
}
sockaddr_in siRecf;
char aryBuf[MAXBYTE] = { 0 };
int nNameLen = sizeof(siRecf);
while (true)
{
nRet = recvfrom(sockServer, aryBuf, sizeof(aryBuf), 0, (sockaddr *)&siRecf, &nNameLen);
if (nRet == SOCKET_ERROR)
{
printf("接收信息错误\r\n");
WSACleanup();
return 0;
}
std::cout << "收到客户端信息:" << aryBuf << std::endl;
char aryBuf[MAXBYTE] = { "hello Server" };
printf("请输入要发送的数据\r\n");
std::cin >> aryBuf;
nRet = sendto(sockServer, aryBuf, sizeof(aryBuf), 0, (sockaddr *)&siRecf, sizeof(siRecf));
if (nRet == SOCKET_ERROR)
{
printf("发送数据错误 \r\n");
WSACleanup();
return 0;
}
}
closesocket(sockServer);
WSACleanup();
return 0;
}
客户端代码也是差不多:
#include <iostream>
#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockClient == INVALID_SOCKET)
{
printf("创建socket失败 \r\n");
return 0;
}
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(0x77988);
si.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int nRet = bind(
sockClient,
(sockaddr *)&si,
sizeof(si)
);
if (nRet == SOCKET_ERROR)
{
printf("绑定端口失败\r\n");
WSACleanup();
return 0;
}
sockaddr_in siSever;
siSever.sin_family = AF_INET;
siSever.sin_port = htons(0x5566);
siSever.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
while (true)
{
char aryBuf[MAXBYTE] = { "hello Server" };
printf("请输入要发送的数据\r\n");
cin >> aryBuf;
nRet = sendto(sockClient, aryBuf, sizeof(aryBuf), 0, (sockaddr *)&siSever, sizeof(siSever));
if (nRet == SOCKET_ERROR)
{
printf("发送数据错误 \r\n");
WSACleanup();
return 0;
}
sockaddr_in siRecf;
char aryBuf2[MAXBYTE] = { 0 };
int nNameLen = sizeof(siRecf);
nRet = recvfrom(sockClient, aryBuf2, sizeof(aryBuf2), 0, (sockaddr *)&siRecf, &nNameLen);
if (nRet == SOCKET_ERROR)
{
printf("接收信息错误\r\n");
WSACleanup();
return 0;
}
cout <<"收到服务端信息:" <<aryBuf2 << endl;
}
closesocket(sockClient);
WSACleanup();
return 0;
}
效果图:
上面输入 I come from China 服务端分开接收到, 是因为客户端cin没有一次性接收到一行,可以改用cin.getline
接下来看TCP例子就简单多了
TCP服务端:
#include <iostream>
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
DWORD WINAPI HandleClientThreadFunc(LPVOID lpParam) {
SOCKET sockClient = *((SOCKET*)lpParam);
while (true)
{
char buf[MAXBYTE] = { 0 };
int iResult = recv(sockClient, buf, MAXBYTE, 0);
if (iResult > 0)
printf("Bytes received: %d content %s \n", iResult, buf);
else if (iResult == 0) {
printf("Connection closed\n");
return 0;
}
else {
printf("recv failed: %d\n", WSAGetLastError());
return 0;
}
char aryBuffSend[] = { "server recv ok \r\n" };
int nRet = send(sockClient, aryBuffSend, sizeof(aryBuffSend), 0);
if (nRet == SOCKET_ERROR)
{
printf("发送错误\r\n");
}
}
closesocket(sockClient);
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockServer == INVALID_SOCKET)
{
printf("socket创建失败 ,请重启\r\n");
return 0;
}
sockaddr_in siServer;
siServer.sin_family = AF_INET;
siServer.sin_port = htons(0x5566);
int nRet = InetPton(AF_INET, "127.0.0.1", &siServer.sin_addr.s_addr);
if (nRet != 1)
{
printf("错误");
return 0;
}
nRet = bind(sockServer, (sockaddr*)&siServer, sizeof(siServer));
if (nRet == SOCKET_ERROR)
{
printf("绑定端口失败,请重启 \r\n");
return 0;
}
nRet = listen(sockServer, SOMAXCONN);
if (nRet != 0)
{
printf("绑定端口失败,请重启 \r\n");
return 0;
}
int len;
sockaddr_in si;
int nLen = sizeof(si);
while (true)
{
SOCKET resultSocket = accept(sockServer, (sockaddr*)&si, &nLen);
if (resultSocket == INVALID_SOCKET)
{
printf("accept失败,请重启 \r\n");
continue;
}
HANDLE handle = CreateThread(NULL, 0, HandleClientThreadFunc, &resultSocket, 0, NULL);
CloseHandle(handle);
}
closesocket(sockServer);
WSACleanup();
}
tcp客户端
#include <iostream>
#include <iostream>
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#include<stdio.h>
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockClient == INVALID_SOCKET)
{
printf("socket创建失败 ,请重启\r\n");
return 0;
}
sockaddr_in siServer;
siServer.sin_family = AF_INET;
siServer.sin_port = htons(0x5566);
int nRet = InetPton(AF_INET, "127.0.0.1", &siServer.sin_addr.s_addr);
nRet = connect(sockClient, (sockaddr*)&siServer, sizeof(siServer));
if (nRet== SOCKET_ERROR)
{
printf("连接服务器失败,请重试\r\n");
return 0;
}
while (true)
{
char aryBuffSend[] = { "Hi,I'm client \r\n" };
printf("请输入发送的数据\r\n");
std::cin >> aryBuffSend;
nRet = send(sockClient, aryBuffSend, sizeof(aryBuffSend), 0);
if (nRet == SOCKET_ERROR)
{
printf("发送错误\r\n");
}
char buf[MAXBYTE] = { 0 };
int iResult = recv(sockClient, buf, MAXBYTE, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else {
printf("recv failed: %d\n", WSAGetLastError());
}
printf("收到信息:%s", buf);
}
closesocket(sockClient);
WSACleanup();
}
ICMP相关代码
#include <iostream>
#include <iostream>
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#include<stdio.h>
typedef struct tagICMP {
BYTE type;
BYTE code;
WORD checksum;
WORD ident;
WORD seq;
BYTE data[32];
}ICMP, *PICMP;
unsigned short in_cksum(unsigned short *addr, int len)
{
int sum = 0;
unsigned short res = 0;
while (len > 1) {
sum += *addr++;
len -= 2;
}
if (len == 1) {
*((unsigned char *)(&res)) = *((unsigned char *)addr);
sum += res;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
res = ~sum;
return res;
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sock == INVALID_SOCKET)
{
printf("socket创建失败 ,请重启\r\n");
WSACleanup();
return 0;
}
ICMP icmp;
icmp.type = 8;
icmp.code = 0;
icmp.checksum = 0;
memcpy(icmp.data, "abcdefghijklmnopqrstuvwabcdefghi", sizeof icmp.data);
icmp.checksum = in_cksum((unsigned short *)&icmp, sizeof(icmp));
struct hostent FAR* pHostent = gethostbyname("www.baidu.com");
sockaddr_in siServer;
siServer.sin_family = AF_INET;
siServer.sin_port = 0;
siServer.sin_addr.S_un.S_addr = *(PULONG)pHostent->h_addr_list[0];
int nRet = sendto(sock, (char *)&icmp, sizeof(icmp), 0, (sockaddr*)&siServer, sizeof(siServer));
if (nRet == SOCKET_ERROR)
{
printf("发送数据失败");
WSACleanup();
return 0;
}
sockaddr_in siRecv;
int nNameLen = sizeof(siRecv);
char aryBuf0[MAXBYTE] = { 0 };
nRet = recvfrom(sock, aryBuf0, sizeof aryBuf0, 0, (sockaddr*)&siRecv, &nNameLen);
if (nRet == SOCKET_ERROR)
{
printf("收到数据失败");
WSACleanup();
return 0;
}
closesocket(sock);
WSACleanup();
}
|