基础网络函数介绍及其Cpp实例(C++)

279 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

基础网络函数介绍(C++)

头文件 winsock2.h 库文件 ws2_32.lib

创建套接字

SOCKET socket(协议族类型,协议类型,协议); 协议族: AF_INET(IPV4协议) AF_INET6(IPV6协议) 协议类型:SOCK_STREAM(流式协议TCP) SOCK_DGRAM(报文协议 UDP) 协议:可以填写0自适应协议
也可以根据协议类型填写[SOCK_STREAM对应IPPROTO_TCP] [SOCK_DGRAM 对应IPPROTO_UDP] 返回值: 成功返回SOCKET句柄,失败返回INVALID_SOCKET

SOCKET sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET == sock)
    printf("创建socket失败\n");

sockaddr_in 结构体

struct in_addr{
    in_addr_t  s_addr;  //32位的IP地址
};

struct sockaddr_in{
    sa_family_t     sin_family;   //地址族(Address Family),也就是地址类型
    uint16_t        sin_port;     //16位的端口号
    struct in_addr  sin_addr;     //32位IP地址
    char            sin_zero[8];  //不使用,一般用0填充 字节对齐
};

//创建sockaddr_in结构体变量
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));  //每个字节都用0填充
addr.sin_family = AF_INET;  //使用IPv4地址
addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
addr.sin_port = htons(7890);  //端口

bind函数

将 SOCKET语句和创建的 sockaddr_in结构体进行关联 在本地打开一个端口 int bind(SOCKET sock, const struct sockaddr* addr , int len); sock:创建的SOCKET句柄 addr:定义的struct sockaddr_in结构体 len:struct sockaddr_in的长度 返回值:0表示成功 -1表示失败

int nRet = bind(sock,(struct sockaddr*)&addr,sizeof(addr));
if(0!=nRet)
    printf("bind Error\n");

listen函数

// 让SOCKET进入监听状态
// int listen(SOCKET sock, int backlog); 
// sock:

Cpp实例

使用socket创建C++服务端。

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>

//网络库文件
#include <winsock2.h>
//引入ws2_32.lib
#pragma comment(lib,"ws2_32.lib")

int	main()
{
	//在window下面需要额外的加载socket库
	WSAData wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("create WSAStartip Error %d\n", GetLastError());
		return 0;
	}


	//1.创建一个socket
	//socket(协议类型IP V4 IPV6,传输类型TCP UDP,0 可选择TCP或其它,0表示自动根据前面两个参数进行自动选择)
	//tcp叫做流式协议
	//SOCK_STRAM ==> TCP
	//SOCK_DGRAM ==> UDP
	SOCKET serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//0 or IPPROTO_TCP
	if (INVALID_SOCKET == serverSock)
	{
		printf("create socket Error %d\n", GetLastError());
		return 0;
	}

	//2.IP端口和SOCKET关联
	//bind 会通过头两个字节,判断真实的数据结构大小,然后比较携带的头和头后面的数据是否一样
	//失败返回INVALID_SOCKET,bind(句柄,IP端口地址结构体,第二个形参的字节大小);

	//SOCKADDR;//16字节
	SOCKADDR_IN serverAddr;//16字节
	serverAddr.sin_family = AF_INET;//协议族类型,IPV4协议族
	//host to network short
	//必须是网络字节序,网络字节序转化为主机字节序时,一定要注意是否需要转换。网络字节序采用大端(big-endian)排序方式。
	//字节序是指大于一个字节类型的数据在内存中的存放顺序。是在跨平台和网络编程中时常要考虑的问题
	//大端:高位字节排放在内存中的低地址端,低位字节排放在内存中的高地址端。
	//小端:低位字节排放在内存中的低地址端,高位字节排放在内存中的高地址端。
	//00 ff(255) 大端
	//ff 00		 小端
	serverAddr.sin_port = htons(7890);
	//127.0.0.1 localhost 永远指向本机
	//0.0.0.0 绑定所有的端口
	//inet_addr将点分十进制的字符串转化为网络地址
	serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//点分十进制
	if (INVALID_SOCKET == bind(serverSock, (sockaddr *)&serverAddr, sizeof(SOCKADDR_IN)))
	{
		printf("bin Error %d\n", GetLastError());
		return 0;
	}
	printf("bind ok\n");

	//3.监听端口
	//允许最大排队数量
	//listen(监听句柄, 监听队列数量);
	if (INVALID_SOCKET == listen(serverSock, 5))
	{
		printf("listen Error %d\n", GetLastError());
		return 0;
	}
	printf("listen ok\n");


	while (true)
	{
		printf("Hold User\n");
		//4.等待用户连接
		//accept(服务端句柄, 客户端IP和端口, 第二个参数的大小);
		SOCKET clientSocket;
		SOCKADDR_IN clientAddr;
		int clientAddrLen = sizeof(SOCKADDR_IN);
		clientSocket = accept(serverSock, (sockaddr *)&clientAddr, &clientAddrLen);
		if (INVALID_SOCKET == clientSocket)
		{
			printf("accept Error %d\n", GetLastError());
			return 0;
		}
		printf("accpet Ok SOCKET[%d] ip[%s] port[%d]\n",
			clientSocket, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

		//5.向连接的客户端发送数据
		//发送的数据长度 = send(句柄, 数据, 数据长度, 0);
		char buffer[1024] = "hello world";
		printf("length:%d\n", send(clientSocket, buffer, strlen(buffer) + 1, 0));
		//关闭客户端
		closesocket(clientSocket);
	}
	//关闭服务端
	closesocket(serverSock);
	return 0;
}

版权声明:本文为CSDN博主「ufgnix0802」的原创文章:
原文链接:(blog.csdn.net/qq135595696…)