Win32编程(第十三天)windows网络通讯之tcp

windows网络通讯:1、网络常识;2、socket;3、tcp通信;4、udp通信
网络架构:七层,五层架构(基于功能或者协议来划分)
7层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
5层:应用层(应用层,表示层,会话层),传输层,网络层,数据链路层,物理层
tcp/ip是一个协议族
socket ip地址,端口号(源ip地址与目标地址ip以及源端口号和目标端口号的组合称为套接字)

tcp通信 建立稳定连接
服务端代码:

//c/s模型(一对一)
//1、准备工作,导头文件
//2、确定版本信息,确定socket版本,ipv4和ipv6版本,win32编程使用ipv4版本
//3、创建socket
//4、初始化协议地址族
//5、绑定(把协议地址族和socket绑定在一起)(注意:客户端不需要绑定)
//6、监听(客户端不需要监听)
//7、服务端:接受监听;客户端:连接
//8、开始通讯
//9、关闭socket

//1、准备工作,导头文件
#include<WinSock2.h>
#include<stdlib.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR *argv[])
{

//2、确定版本信息
WSADATA wsaData;
//第1个参数是版本请求,请求哪个版本,高阶字节指的是修订版本,低阶字节指的是主版本号
//第二个参数是一个结构体,用来接收socket实现的细节
WSAStartup(MAKEWORD(2, 2), &wsaData);//异步实现套接字的启动命令
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
	printf("请求版本失败,启动不成功\n");
	getchar();
	
	return -1;
}
printf("请求版本成功\n");
//3、创建socket
//第1个参数协议族,表示当前socket要用什么类型的地址和端口
//AF_INET表示要用ipv4的地址(32位)与端口号(16位)的组合
//
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == serverSocket)
{
	printf("套接字创建失败\n");
	WSACleanup();//关闭套接字请求
	system("pause");
	return -1;
}
printf("套接字创建成功\n");
//4、初始化协议地址族
SOCKADDR_IN serverAddr = { 0 };//初始化一下协议地址
serverAddr.sin_family = AF_INET;//必须和第3步创建socket时的参数一致
//端口号需要存储,需要注意:网络的数值和pc的存储数值是有区别的,pc是先存低位再存高位(小端)
//			在网络是(大端)先是高位再是低位,把pc的数值转为网络htons来转换
serverAddr.sin_port = htons(8888);//这是服务端的端口,客户端要通过这个端口才能连接
//ip地址的表示是点分格式的字符串,用inet_addr来转换为整数
serverAddr.sin_addr.S_un.S_addr = inet_addr("10.214.74.106/15");
//5、绑定
//第2个参数为协议地址族的首地址
if (SOCKET_ERROR == bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)))
{
	printf("绑定失败\n");
	closesocket(serverSocket);//释放socket
	WSACleanup();//关闭套接字请求
	getchar();
	return -1;
}
printf("绑定成功\n");
//6、监听
//第2个参数是监听的个数。是等待连接的队列的最大长度
if (SOCKET_ERROR == listen(serverSocket, 10))
{
	printf("监听失败\n");
	closesocket(serverSocket);
	WSACleanup();
	getchar();
	return -1;
}
printf("监听成功\n");

//7、接受连接
	//第2个参数和第3个参数可以
	SOCKADDR_IN clientAddr = { 0 };
	int len = sizeof(clientAddr);
	SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr,&len);
	if (clientSocket == INVALID_SOCKET)
	{
		printf("连接失败\n");
		closesocket(serverSocket);
		WSACleanup();
		return -1;
	}
	printf("连接失败\n");
	printf("有客户连接进来,客户端的ip:%s\n", inet_ntoa(clientAddr.sin_addr));
	//8、开始通讯
	char buff[128] = {};
	while (1)
	{
		memset(buff, 0, sizeof(buff));
		//第一个参数代表客户端socket,表示客户端进行接收数据
		//第4个参数表示接收方式,0表示默认方式,一次收完
		if (recv(clientSocket, buff, sizeof(buff)-1, 0) > 0)//阻塞函数
		{
			printf(">>:%s\n", buff);
		}
		char clientbuff[128] = {};
		memset(clientbuff, 0, sizeof(clientbuff));
		printf("请输入:");
		scanf_s("%s", clientbuff, sizeof(clientbuff)-1);
		send(clientSocket, clientbuff, strlen(clientbuff), 0);
	}
	//9、关闭socket
	closesocket(clientSocket);
	closesocket(serverSocket);
	WSACleanup();
	system("pause");
	return 0;
}

客户端代码:

#include "stdafx.h"
//开始准备工作,导头文件
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS 

int _tmain(int argc, _TCHAR* argv[])
{

	//2、确定版本信息
	WSADATA wsaData;
	//第1个参数是版本请求,请求哪个版本,高阶字节指的是修订版本,低阶字节指的是主版本号
	//第2个参数是一个结构体,用来接收socket实现的细节
	WSAStartup(MAKEWORD(2, 2), &wsaData);//异步套接字的启动命令
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("请求版本失败,启动不成功\n");
		return -1;
	}
	printf("请求版本成功\n");
	//3、创建socket
	//第1个参数协议族,表示当前socket要用什么类型的地址和端口
	//第2个参数表示类型,SOCK_STREAM表示流式socket,面向连接socket
	//第3个参数指定协议  IPPROTO_TCP  表示tcp传输协议
	//返回一个socket
	SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == clientSocket)
	{
		printf("套接字创建失败\n");
		WSACleanup();//关闭套接字请求
		return -1;
	}
	printf("套接字创建成功\n");
	//4、初始化协议地址族(初始化的是给服务端ip地址及端口)
	SOCKADDR_IN clientAddr = { 0 };//初始化一下协议地址
	clientAddr.sin_family = AF_INET;//必须和第3步创建socket时参数一致
	//端口号需要存储,需要注意:网络的数值和pc的存储数值是有区别的,pc是先存低位,再存高位(小端)
	//在网络是(大端)先是高位再是低位,把pc的数值转化为网络htons来转换
	clientAddr.sin_port = htons(8888);//这是服务的端口,客户端通过这个端口才能连接
	//ip地址的表示是点分格式的字符串,用inet_addr来转换为整数
	clientAddr.sin_addr.S_un.S_addr = inet_addr("10.214.74.106/15");

	//5、连接
	if (SOCKET_ERROR == connect(clientSocket, (sockaddr*)&clientAddr, sizeof(clientAddr)))
	{
		printf("连接失败\n");
		closesocket(clientSocket);//释放socket
		WSACleanup();//关闭套接字请求
		return -1;
	}
	printf("连接不成功\n");
	//开始通讯
	char buff[128] = {};
	while (1)
	{
		memset(buff, 0, sizeof(buff));
		printf("请输入:");
		scanf_s("%s", buff, sizeof(buff)-1);
		send(clientSocket, buff, strlen(buff), 0);//send发消息是发给clientSocket所指的ip和端口
		char mm[128] = {};
		if (recv(clientSocket, mm, sizeof(mm)-1, 0) > 0);//阻塞函数
		{
			printf(">>:%s\n", mm);
		}

	}
	//关闭socket
	closesocket(clientSocket);
	WSACleanup();//关闭套接字请求
	getchar();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41848597/article/details/89318716