Windows编程(⽹络编程)
Windows编程(⽹络编程)
套接字类型与协议设置
SOCK_STREAM[流套接字] TCP
⾯向连接、可靠的数据传输适合传输⼤量的数据,不⽀持⼴播、多播
SOCK_DGRAM[数据包套接字] UDP
⽆连接⽀持⼴播、多播
SOCK_RAW[原始套接字]
可以读写内核没有处理的 IP 数据报
避开 TCP/IP 处理机制,被传送的数据报可以被直接传送给需要它的的应⽤程序
-引⽤头⽂件 winsock2.h
-
导⼊ ws2_32.lib 库
- window 下 socket 编程都要⾸先进⾏ Winsock 的初始化
使⽤:
SOCKET WSAAPI socket(
int af,
int type,
int protocol
);
af参数:
当前⽀持的值为 AF_INET 或 AF_INET6,它们是 IPv4 和 IPv6 的 Internet 地址族格式。如果安装了地址族的 Windows 套接字服务提供程序,则⽀持地址族的其他选项(例如,⽤于 NetBIOS 的 AF_NETBIOS)。请注意,AF_ 地址族和 PF_ 协议族常量的值是相同的(例如,AF_INET和PF_INET)
,因此可以使⽤任⼀常量。
AF_UNSPEC0地址族未指定。
**AF_INET **Internet 协议版本 4 (IPv4) 地址族。
AF_IPX IPX/SPX 地址族。仅当安装了 NWLink IPX/SPX NetBIOS 兼容传输协议时才⽀持此地址系列。Windows Vista 及更⾼版本不⽀持此地址系列。
AF_APPLETALK AppleTalk 地址族。仅当安装了 AppleTalk 协议时才⽀持此地址族。Windows Vista 及更⾼版本不⽀持此地址系列。
AF_NETBIOS NetBIOS 地址族。仅当安装了 NetBIOS 的 Windows 套接字提供程序时才⽀持此地址族。32 位版本的 Windows ⽀持NetBIOS 的 Windows 套接字提供程序。默认情况下,此提供程序安装在 32 位版本的 Windows 上。64 位版本的Windows 不⽀持 NetBIOS 的 Windows 套接字提供程序,包括 Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003 或 Windows XP。NetBIOS 的 Windows 套接字提供程序仅⽀持类型参数设置为SOCK_DGRAM 的套接字。NetBIOS 的 Windows 套接字提供程序与编程接⼝没有直接关系。Windows Vista、Windows Server 2008及更⾼版本不⽀持 NetBIOS 编程接⼝。
AF_INET6Internet 协议版本 6 (IPv6) 地址族。
AF_IRDA红外数据协会 (IrDA) 地址族。仅当计算机安装了红外端⼝和驱动程序时,才⽀持此地址族。
AF_BTH蓝⽛地址族。如果计算机安装了蓝⽛适配器和驱动程序,则 Windows XP SP2 或更⾼版本⽀持此地址系列。
type参数:
新套接字的类型规范。
套接字类型的可能值在Winsock2.h头⽂件中定义。
在 Windows Sockets 1.1 中,唯⼀可能的套接字类型是SOCK_DGRAM和SOCK_STREAM。
类型意义
SOCK_STREAM⼀种套接字类型,通过 OOB 数据传输机制提供有序的、可靠的、双向的、基于连接的字节流。此套接字类型使⽤Internet 地址族(AF_INET 或 AF_INET6)的传输控制协议 (TCP)。
SOCK_DGRAM⽀持数据报的套接字类型,数据报是固定(通常很⼩)最⼤长度的⽆连接、不可靠的缓
冲区。此套接字类型使⽤Internet 地址族(AF_INET 或 AF_INET6)的⽤户数据报协议 (UDP)。
SOCK_RAW提供原始套接字的套接字类型,允许应⽤程序操作下⼀个上层协议标头。要操作 IPv4 标头,必须在套接字上设置套接字选项。要操作 IPv6 标头,必须在套接字上设置套接字选项。
SOCK_RDM提供可靠消息数据报的套接字类型。这种类型的⼀个例⼦是 Windows 中的实⽤通⽤多播 (PGM) 多播协议实现,通常称为。仅当安装了可靠多播协议时才⽀持此类型值。
SOCK_SEQPACKET⼀种基于数据报提供伪流数据包的套接字类型。
protocol参数
要使⽤的协议。协议参数的可能选项特定于指定的地址族和套接字类型。协议的可能值在Winsock2.h和Wsrm.h头⽂件中定义。
在为 Windows Vista 及更⾼版本发布的 Windows SDK 上,头⽂件的组织已更改,此参数可以是Ws2def.h头⽂件中定义的IPPROTO枚举类型的值之⼀。请注意,Ws2def.h头⽂件⾃动包含在Winsock2.h 中,不应直接使⽤。
如果指定值为 0,则调⽤者不希望指定协议,服务提供者将选择要使⽤的协议。
当af参数为 AF_INET 或 AF_INET6 且类型为SOCK_RAW 时,在 IPv6 或 IPv4 数据包头的协议字段中设置为协议指定的值。
协议意义
IPPROTO_ICMP Internet 控制消息协议 (ICMP)。当af参数为AF_UNSPEC、AF_INET或AF_INET6并且类型参数为SOCK_RAW 或未指定时,这是⼀个可能的值。Windows XP 及更⾼版本⽀持此协议值。
IPPROTO_IGMP Internet 组管理协议 (IGMP)。当af参数为AF_UNSPEC、AF_INET或AF_INET6并且类型参数为SOCK_RAW或未指定时,这是⼀个可能的值。Windows XP 及更⾼版本⽀持此协议值。
BTHPROTO_RFCOMM蓝⽛射频通信 (Bluetooth RFCOMM) 协议。当af参数为AF_BTH且类型参数为SOCK_STREAM时,这是⼀个可能的值。带有 SP2 或更⾼版本的 Windows XP ⽀持此协议值。
IPPROTO_TCP传输控制协议 (TCP)。当af参数为AF_INET或AF_INET6并且类型参数为SOCK_STREAM时,这是⼀个可能的
IPPROTO_TCP传输控制协议 (TCP)。当af参数为AF_INET或AF_INET6并且类型参数为SOCK_STREAM时,这是⼀个可能的值。
IPPROTO_UDP⽤户数据报协议 (UDP)。当af参数是AF_INET或AF_INET6并且类型参数是SOCK_DGRAM时,这是⼀个可能的值。
IPPROTO_ICMPV6Internet 控制消息协议版本 6 (ICMPv6)。当af参数为AF_UNSPEC、AF_INET或AF_INET6 并且类型参数为SOCK_RAW或未指定时,这是⼀个可能的值。Windows XP 及更⾼版本⽀持此协议值。
IPPROTO_RM ⽤于可靠组播的 PGM 协议。当af参数是AF_INET并且类型参数是SOCK_RDM时,这是⼀个可能的值。在为Windows Vista 及更⾼版本发布的 Windows SDK 上,此协议也称为IPPROTO_PGM。仅当安装了可靠多播协议时才⽀持此协议值。
协议意义
TCP 通讯
SOCKADDR_IN
原型:
typedef struct sockaddr_in {
USHORT sin_port;//16 位地址类型
IN_ADDR sin_addr;//16 位端⼝号 65535 2 的 16 次⽅
CHAR sin_zero[8];//8 字节填充
}
IN_ADDR:
#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2 // host on imp
#define s_net S_un.S_un_b.s_b1 // network
#define s_imp S_un.S_un_w.s_w2 // imp
#define s_impno S_un.S_un_b.s_b4 // imp #
#define s_lh S_un.S_un_b.s_b3 // logical host
Server端
代码实例:
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include<stdio.h>
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main() {
//1 初始化⽹络库
/
/ 加载套接字库
WORD wVersionRequested; WSADATA wsaData;
int err; wVersionRequested = MAKEWORD(2, 2);
// 1、初始化套接字库
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) { printf("WSAStartup errorNum = %d\n", GetLastError());
return err;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("LOBYTE errorNum = %d\n", GetLastError());
WSACleanup();
return -1;
}
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sockSrv) {
printf("socket errorNum = %d\n", GetLastError());
return -1;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任意地址连接
addrSrv.sin_family = AF_INET; //设置ipv4
addrSrv.sin_port = htons(6001); //设置端⼝
if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))) { printf("bind errorNum = %d\n", GetLastError()); return -1;
}
if (SOCKET_ERROR == listen(sockSrv, 5)) {
printf("listen errorNum = %d\n", GetLastError()); return -1;
}
SOCKADDR_IN addrCli;
int len = sizeof(SOCKADDR);
while (TRUE) {
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli, &len);//创建socket并进⾏阻塞
char sendBuf[100] = { 0 };
sprintf_s(sendBuf, 100, "Welcome %s to bingo!", inet_ntoa(addrCli.sin_addr));
//发送数据
int iLen = send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
if (iLen < 0) {
printf("send errorNum = %d\n", GetLastError()); return -1;
}
char recvBuf[100] = {0};
iLen = recv(sockConn, recvBuf, 100, 0); //接收数据
if (iLen < 0) {
printf("recv errorNum = %d\n", GetLastError());
return -1; }//打印接收的数据
printf("recvBuf = %s\n", recvBuf);
closesocket(sockConn);
}
}
什么是编程举个例子创建Socket后调⽤bind()绑定本机监听地址。并且listen()设置监听连接请求。accept()接受请求,并且进⾏阻塞。如果有会话连接过来可以调⽤recv()和send()进⾏接受和发送数据。
Client端
#include<iostream>
#include<WinSock2.h>
#include<stdio.h>
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#include<Windows.h>
#include<stdlib.h>
int main() {
printf("Client\n");
char sendBuf[] = "hello,world";
//1 初始化⽹络库 // 加载套接字库
WORD wVersionRequested;
WSADATA wsaData; int err;
wVersionRequested = MAKEWORD(2, 2);
// 1、初始化套接字库
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
printf("WSAStartup errorNum = %d\n", GetLastError());
return err;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("LOBYTE errorNum = %d\n", GetLastError()); WSACleanup();
return -1; }
// 新建套接字
SOCKET socket_cli = socket(AF_INET, SOCK_STREAM,0);
if (INVALID_SOCKET == socket_cli) {
cout << "Error" << endl;
return -1;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.8.104");
addrSrv.sin_port = htons(6001);
addrSrv.sin_family = AF_INET;
cout << "test" << endl;
if (connect(socket_cli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) == SOCKET_ERROR) {
return -1;
}
// 4 接收和发送数据
char recvBuf[100] = { 0 };
int iLen = recv(socket_cli, recvBuf, 100, 0);
if (iLen < 0) {
printf("recv errorNum = %d\n", GetLastError());
return -1;
}
printf("Client recvBuf = %s\n", recvBuf);
iLen = send(socket_cli, sendBuf, strlen(sendBuf) + 1, 0);
if (iLen < 0) {
printf("send errorNum = %d\n", GetLastError());
return -1;
}
closesocket(socket_cli);
WSACleanup();
return 0;
}
UDP通讯
Server端
#include<iostream>
#include<WinSock2.h>
#include<stdio.h>
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#include<Windows.h>
#include<stdlib.h>
int main() {
// 初始化套接字库
WORD wVersion; WSADATA wsaData;
int err; wVersion = MAKEWORD(1, 1);
err = WSAStartup(wVersion, &wsaData);
if (err != 0) {
return err;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; }// 创建套接字
SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
cout << "socket创建成功" << endl;
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6003);
// 绑定套接字
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
// 等待并接收数据
SOCKADDR_IN addrCli;
int len = sizeof(SOCKADDR_IN);
char recvBuf[100];
char sendBuf[100];
while (true) {
std::cout << "循环" << std::endl;
recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len);
std::cout << recvBuf << std::endl;
sprintf_s(sendBuf, 100, "Ack %s", recvBuf);
sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrCli, len);
}closesocket(sockSrv);
WSACleanup();
system("pause");
return 0;
}
Client端:
int main() {
{ // 加载套接字库
WORD wVersion;
WSADATA wsaData;
int err; wVersion = MAKEWORD(1, 1);
err = WSAStartup(wVersion, &wsaData);
if (err != 0) {
return err;
}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
WSACleanup(); return -1; }
// 创建套接字
SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_port = htons(6001);
addrSrv.sin_family = AF_INET;
int len = sizeof(SOCKADDR); char sendBuf[] = "hello";
char recvBuf[100]; //发送数据
sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)& addrSrv, len); recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR*)& addrSrv, &len);
std::cout << recvBuf << std::endl;
closesocket(sockCli);
system("pause"); return 0; }
}
TCP与UDP适⽤场景
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论