本帖最后由 鸦领主 于 2021-2-18 18:35 编辑
网络函数
=============================
WSAStartup函数
int WSAAPI WSAStartup(i,&WSADATA):返回值0就是正确的没问题
返回值是int类型
in_i--版本号,最高版本就是514,十六进制0x0202
ot_WSADATA--定义一个WSADATA类型的结构体
写法:
WSADATA wsaData;
WSAStartup(0x0202,&wsaData);
这个函数是用来加载socket库,不可不写
======================
socket函数:创建套接字(也可以称为句柄)
SOCKET WSAAPI socket(
int af,
int type,
int protocol
);
af--AF_INET 一般情况一下这个参数就是写入AF_INET
type--一般情况下选择SOCK_DGRAM(UDP)或SOCK_STREAM(TCP)
protocol--0 一般情况下这个参数就是0
返回值:SOCKET(类型)
写法:
socket(AF_INET,SOCK_DGRAM,0);
===================================
bind:绑定函数(这个绑定函数将本地地址与套接字相关联)
nt WSAAPI bind(
SOCKET s,
const sockaddr *name,
int namelen
);
s--要被绑定的套接字(句柄)
nmae--sockaddr类型的结构体对象
namelen--结构体的长度
返回值:int(类型)
sockaddr_in:地址信息结构体:端口和IP,因为sockaddr无法指定端口和IP所以要用sockaddr_in
写法:
sockaddr_in sa = {2} 指定一个对象,写法必须写入一个2(AF_INET)
sa.sin_port = htons(9000); //写入端口
sa.sin_addr.S_un.S_addr = inet_addr("192.168.10.250");//写入ip,绑定时ip指定为0,代表本机ip全部绑定进去,否者只绑定指定的ip
//端口是自己随便定义的,ip是本地的ip,或则不指定写入0
bind(sock,(sockaddr*)&sa,sizeof(sa));//因为结构体要的是sockaddr而我们用的是sockaddr_in 需要强制转换一下
htons:将整数形式的ip端口转化为网络字节序
列如:我带入8888,十六进制为0x22b8,在转换0xb822,转化为十进制是47138
inet_addr:将字符串形式的IP地址 转换为网络字节顺序 的整型值
列如:带入ip是“192.168.10.250”每一段将拆分拆分为4断,每一段都将转换为16进制0xc0,0xa8,0x0a,0xfa,
在进行相反的合并为0xfa0aa8c0,10进制显示是4195002560
inet_ntoa:和inet_addr是相反的
硬件开发商对内存变量的排布有两种方法:
一种是主机字节顺序:个位在低字节上, short s = 0x1234 ;0x34将存在内存地址较小的位置上,0x12存在地址较大的位置上
一种是网络字节顺序:个位在高字节上,short s =0x1234 ; 0x34将存在内存地址较大的位置上,0x12存在地址较小的位置上
sockaddr_in sa=结构体中端口,必须用网络字节顺序,因此每次都要调用htons进行转化
======================================
recv:从连接的套接字或绑定的无连接套接字接收数据(接收信息)
int WSAAPI recv(
SOCKET s,
char *buf,
int len,
int flags
);
s--绑定的套接字(句柄)
buf--指向接收传入数据的缓冲区的指针。
len--指向的缓冲区的长度
flags--固定填入0
写法:
char c[1024]
recv(sock,s,sizeof(s),0);
===============================
recvfrom:这个recvfrom函数接收数据报,并存储源地址。
//和recv区别不大,多了俩个参数
int WSAAPI recvfrom(
SOCKET s,
char* buf,
int len,
int flags,
sockaddr* from,
int* fromlen
);
s--绑定的套接字(句柄)
buf--指向接收传入数据的缓冲区的指针。
len--指向的缓冲区的长度
flags--固定填入0
from--结构体对象(源地址将保存在这里)
fromlen--对象长度
====================================
sendto:将数据发送到特定目标(发送信息)
int WSAAPI sendto(
SOCKET s,
const char *buf,
int len,
int flags,
const sockaddr *to,
int tolen
);
s--定义的套接字
buf--指向接收传入数据的缓冲区的指针。
len--向的缓冲区的长度
flags--固定填入0
to--定义的地址信息结构体的对象
tolen--to的长度
列子:
发送端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<winSock2.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
SOCKET sock = socket(AF_INET, SOCK_DGRAM,0);
sockaddr_in sa = {2};
sa.sin_port = htons(9151);//指定要发送的端口(端口要和接收端的端口一样)
sa.sin_addr.S_un.S_addr = inet_addr("192.168.1.9");//和对应的电脑ip地址
while (true)
{
char s[50];
gets_s(s,sizeof(s));
//cin >> s;
if(!(s[0]==0))
sendto(sock, s, strlen(s), 0, (sockaddr*)&sa, sizeof(sa));
}
}
接收端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<winSock2.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
enum { PORT=9151};
int main()
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);//创建一个套接字
sockaddr_in sa = { 2,htons(9151),0 };
int n=bind(sock, (sockaddr*)&sa, sizeof(sa));//sock与ip和端口绑定
int nLen = sizeof(sa);
while (true)
{
char s[50] = {0};
recvfrom(sock, s, sizeof(s), 0,(sockaddr*)&sa,&nLen);
cout << "IP:" << inet_ntoa(sa.sin_addr) << " | PORT:" << htons(sa.sin_port) << endl;
cout << s << endl;
}
return 0;
}
网络应用
2.用MFC的sock类再次编写
接收端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<afxsock.h>
using namespace std;
int main()
{
AfxSocketInit();
CSocket sock;
sock.Create(8888, SOCK_DGRAM);
sockaddr_in sa;
int nLen = sizeof(sa);
char s[128] = {0};
while (true)
{
sock.ReceiveFrom(s, sizeof(s),(sockaddr*)&sa,&nLen);
cout << "IP:" <<inet_ntoa(sa.sin_addr)<<" PORT:"<<htons(sa.sin_port) <<endl<<s<<endl;
}
return 0;
}
发送端
#include<iostream>
#include<afxsock.h>
using namespace std;
int main()
{
AfxSocketInit();
CSocket sock;
sock.Create(0, SOCK_DGRAM);
char s[128];
while (true)
{
cin >> s;
sock.SendTo(s, strlen(s), 8888, _T("192.168.1.9"));
}
}
AfxSocketInit();
就相当于
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
Create :创建套接字
BOOL Create(
UINT nSocketPort = 0,
int nSocketType = SOCK_STREAM,
LPCTSTR lpszSocketAddress = NULL);
三个参数:
nSocketPort--要与套接字一起使用的特定端口,或者如果想要 MFC 选择端口,则为0(默认不填为0)。
nSocketType--选择SOCK_STREAM(TCP协议)或者SOCK_DGRAM(UDP协议)默认为不填为TCP协议
lpszSocketAddress--选择指定的ip,NULL本机所有ip绑定进去(默认不填为NULL)
ReceiveFrom:接收数据并存储源地址
int ReceiveFrom( void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags = 0);
五个参数:
lpBuf :传入数据的缓冲区。 nBufLen :LpBuf 的长度(以字节为单位)。 lpSockAddr :指向 [color=var(--theme-visited)]SOCKADDR 结构的指针,该结构在返回时保存源地址。 lpSockAddrLen :sockaddr结构体对象的长度
nFlags:一般填0(默认不填为0)
SenYo:向特定目标发送数据 int SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0);
五个参数:
lpBuf :包含要传输的数据的缓冲区。
nBufLen :LpBuf 中数据的长度(以字节为单位)。
nHostPort :标识套接字应用程序的端口。 lpszHostAddress :目标ip地址 nFlags:一般填0(默认不填为0)
|