鸦领主 发表于 2021-2-17 16:13:20

c++网络程序开发相关函数

本帖最后由 鸦领主 于 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(
SOCKETs,
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
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;
      gets_s(s,sizeof(s));
      //cin >> s;
      if(!(s==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 = {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 = {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;
    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 :指向 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)

agongzuoshi 发表于 2021-8-21 00:05:30

非常不错啊,感谢楼主无私的共享精神!

xiaoweiwb 发表于 2021-9-20 06:58:47

谢谢分享谢谢分享

xiaoweiwb 发表于 2021-12-8 07:06:40

谢谢分享谢谢分享
页: [1]
查看完整版本: c++网络程序开发相关函数