IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> TCP/IP 基本C/S模型 -> 正文阅读

[网络协议]TCP/IP 基本C/S模型

服务端与客户端通信

服务端:

1.打开网络库

int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);

2.检验版本号

2 != HIBYTE(wsaData.wVersion) || 2 != LOBYTE(wsaData.wVersion)? (检验版本号是 2.2)

3.创建socket 套接字

SOCKET socket(int af, int type, int protocol);

4.绑定地址与端口号

int bind(SOCKET s, const sockaddr* addr, int namelen);

5.进行监听

int WSAAPI listen(SOCKET s, int backlog);

6.接受链接(本质:创建客户端socket)

SOCKET WSAAPI accept(SOCKET s, sockaddr* addr, int *addrlen);

7.与客户端进行收发信息

收:int recv(SOCKET s, char *buf, int len, int flags);

发:int WSAAPI send(SOCKET s, const char *buf, int len, int flags);

客户端

1.打开网络库

int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);

2.检验版本号

2 != HIBYTE(wsaData.wVersion) || 2 != LOBYTE(wsaData.wVersion)? (检验版本号是 2.2)

3.创建socket 套接字(注:创建的socket是服务端的socket)

SOCKET socket(int af, int type, int protocol);

4.链接服务端

int WSAAPI connect(SOCKET s, const sockaddr *name, int namelen);

5.与服务端发收信息

发:int WSAAPI send(SOCKET s, const char *buf, int len, int flags);

收:int recv(SOCKET s, char *buf, int len, int flags);

代码:

服务端:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Winsock.h>
#pragma comment(lib,"ws2_32.lib")

// 定义 WSAStartup 参数2所需的结构体
WSADATA WSAData;
// 定义全局的socket
SOCKET socket_c;
// 1.打开网络库
void Open_WSAStartup()
{
	// 1,打开网络库
	WORD version = MAKEWORD(2, 2);	//设置要使用的库的版本 MAKEWORD(主版本,副版本); 
	int n = WSAStartup(version, &WSAData);
	// 检验是否成功打开网络库
	if (0 != n)
	{
		// 打开网络库失败,通过n 返回的错误码,给出提示
		switch (n)
		{
		case WSASYSNOTREADY:
			printf("重启电脑试试,或者检查ws_2_32库是否存在\n");
			break;
		case WSAVERNOTSUPPORTED:
			printf("当前库版本号不支持,尝试更换版本试试\n");
			break;
		case WSAEPROCLIM:
			printf("已达到对Windows套接字实现支持的任务数量的限制\n");
			break;
		case WSAEINPROGRESS:
			printf("正在阻止Windows Sockets 1.1操作,当前函数运行期间,因为某些原因造成阻塞\n");
			break;
		case WSAEFAULT:
			printf("lpWASData参数不是有效的指针,参数写错了\n");
			break;
		default:
			break;
		}
	}
}

// 2.校验版本
void CheckVersion()
{
	// 2.校验版本
	if (2 != HIBYTE(WSAData.wVersion) || 2 != LOBYTE(WSAData.wVersion))
	{
		// 打开版本号 2.2 失败
		printf("打开版本号 2.2 失败, 正在退出程序...\n");
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return;
	}
}

// 3.创建套接字 socket
SOCKET CreateSocket(SOCKET createSocket)
{
	// 3.创建套接字 socket
	createSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// 检验是否成功创建套接字
	if (INVALID_SOCKET == createSocket)
	{
		// 创建套接字失败
		// 获取错误码
		int error = WSAGetLastError();
		printf("创建套接字失败,返回错误号为:%d\n", error);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return 0;
	}
	return createSocket;
}

// 4.绑定地址与端口号
void Bind(SOCKET socketServer)
{
	// 4.绑定地址与端口号
	// 创建bind() 函数所需的第二个参数的结构体,该结构体装 地址类型,IP地址,端口号
	sockaddr_in server_s;
	server_s.sin_family = AF_INET;	// 地址类型
	server_s.sin_port = htons(12345);			// 端口号
	server_s.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");	// ip地址
	int isbind = bind(socketServer, (struct sockaddr*)&server_s, sizeof(server_s));
	// 检验绑定地址与端口号是否成功
	if (SOCKET_ERROR == isbind)
	{
		// 绑定地址与端口号失败
		// 获取错误号
		int error = WSAGetLastError();
		printf("绑定端口号和IP地址失败,返回错误号为:%d\n", error);
		// 关闭套接字
		closesocket(socketServer);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return;
	}
}

// 5.进行监听
void Listen(SOCKET socketServer)
{
	// 5.进行监听
	if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))
	{
		// 套接字中断了侦听传入连接的状态
		// 获取错误号
		int error = WSAGetLastError();
		printf("监听失败,返回错误号为:%d\n", error);
		// 关闭套接字
		closesocket(socketServer);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return;
	}
}

// 6.进行链接 创建客户端socket
SOCKET Accpet(SOCKET socketServer)
{
	// 6.创建客户端socket,接受连接
	//SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// 创建accpet() 函数参数二所需的结构体体,用来装ip 和端口号
	sockaddr_in client_s;
	//给结构体成员赋值
	client_s.sin_family = AF_INET;	//地址类型
	client_s.sin_port = htons(12345);		//端口号
	client_s.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");	//ip地址
	// 获取结构体的大小
	int len = sizeof(client_s);
	SOCKET c_socketClient = accept(socketServer, (sockaddr*)&client_s, &len);
	// 检验是否设置接收连接状态
	if (INVALID_SOCKET == c_socketClient)
	{
		// 退出了接受链接状态
		// 获取错误号
		int error = WSAGetLastError();
		printf("连接失败,返回错误号为:%d\n", error);
		// 关闭套接字
		closesocket(socketServer);
		// 关闭客户端套接字
		closesocket(c_socketClient);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return 0;
	}
	return c_socketClient;
}

int main()
{
	// 1.打开网络库
	Open_WSAStartup();
	// 2.校验版本
	CheckVersion();
	// 3.创建套接字 socket
	SOCKET socketServer = CreateSocket(socket_c);
	// 4.绑定地址与端口号
	Bind(socketServer);
	// 5.进行监听
	Listen(socketServer);
	// 6.创建客户端socket,接受连接
	SOCKET socketClient = Accpet(socketServer);

	// 与客户端进行收发信息
	// 	   收信息
	// 定义字节数组,用来接收客户端发来的信息的缓存区
	/*char recvBuf[1024] = { 0 };
	recv(socketClient, recvBuf, 1024, 0);
	printf("%s\n", recvBuf);*/
	printf("成功连接,我是服务端,请客户端发送信息...\n");
	while (1)
	{
		//收信息
		char recvBuf[1024] = { 0 };
		int ret = recv(socketClient, recvBuf, 1024, 0);
		// 判断recv 返回值
		if (ret == SOCKET_ERROR)
		{
			// 打印错误码
			printf("recv failed :%d\n", WSAGetLastError());
			// 退出程序
			break;
		}
		else if (ret == 0)
		{
			// 客户端下线了
			printf("Connection closed\n");
			break;
		}
		else
		{
			printf("客户端say : %s\n", recvBuf);	
		}
		// 发信息	
		// 定义发送字节的数组
		char sendBuf[1024] = { 0 };
		scanf_s("%s", sendBuf, 1024);
		send(socketClient, sendBuf, 1024, 0);	
	}
	
	// 注意用完之后要关闭网络库和套接字
	// 关闭套接字
	closesocket(socketServer);
	// 关闭客户端套接字
	closesocket(socketClient);
	// 关闭网络库
	WSACleanup();
	system("pause");
	return 0;
}

客户端:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Winsock.h>
#pragma comment(lib,"ws2_32.lib")

WSADATA WSAData;
// 1,打开网络库
void OpenWSAStarup()
{
	// 1,打开网络库
	WORD version = MAKEWORD(2, 2);	//设置要使用的库的版本 MAKEWORD(主版本,副版本); 
	int n = WSAStartup(version, &WSAData);
	// 检验是否成功打开网络库
	if (0 != n)
	{
		// 打开网络库失败,通过n 返回的错误码,给出提示
		switch (n)
		{
		case WSASYSNOTREADY:
			printf("重启电脑试试,或者检查ws_2_32库是否存在\n");
			break;
		case WSAVERNOTSUPPORTED:
			printf("当前库版本号不支持,尝试更换版本试试\n");
			break;
		case WSAEPROCLIM:
			printf("已达到对Windows套接字实现支持的任务数量的限制\n");
			break;
		case WSAEINPROGRESS:
			printf("正在阻止Windows Sockets 1.1操作,当前函数运行期间,因为某些原因造成阻塞\n");
			break;
		case WSAEFAULT:
			printf("lpWASData参数不是有效的指针,参数写错了\n");
			break;
		}
	}
}
// 2.检验版本
void CheckVersion()
{
	if (2 != HIBYTE(WSAData.wVersion) || 2 != LOBYTE(WSAData.wVersion))
	{
		// 打开版本号 2.2 失败
		printf("打开版本号 2.2 失败, 正在退出程序...\n");
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return;
	}
}
// 3.创建socket
SOCKET CreateSocket()
{
	// 3.创建套接字 socket 创建服务端的socket
	SOCKET socketCreate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// 检验是否成功创建套接字
	if (INVALID_SOCKET == socketCreate)
	{
		// 创建套接字失败
		// 获取错误码
		int error = WSAGetLastError();
		printf("创建套接字失败,返回错误号为:%d\n", error);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return 0;
	}
	return socketCreate;
}
// 4.连接服务器
void Connection(SOCKET socket_)
{
	// 4.连接到服务器
	// 创建connect() 函数中参数2所需的结构体 用来装IP地址和端口号
	sockaddr_in client_s;
	//给结构体成员赋值
	client_s.sin_family = AF_INET;		//IP地址类型
	client_s.sin_port = htons(12345);	//端口号
	client_s.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	int nCon = connect(socket_, (struct sockaddr*)&client_s, sizeof(client_s));
	// 检验是否成功连接到服务端
	if (SOCKET_ERROR == nCon)
	{
		// 连接服务端失败
		// 获取错误码
		int error = WSAGetLastError();
		printf("连接服务端失败,返回错误号为:%d\n", error);
		// 关闭套接字
		closesocket(socket_);
		// 关闭网络库
		WSACleanup();
		// 退出程序
		return;
	}
}

int main()
{
	// 1,打开网络库
	OpenWSAStarup();
	// 2.校验版本
	CheckVersion();
	// 3.创建socket
	SOCKET socketServer = CreateSocket();
	// 4.连接服务器
	Connection(socketServer);
	
	printf("我是客户端,正在发送信息,请稍等...\n");
	
	//send(socketServer, "来自客户端的信息...", sizeof("来自客户端的信息..."), 0);

	// 5.与服务端进行收发信息
	while (1)
	{
		// 发信息
		char sendBuf[1024] = { 0 };
		scanf_s("%s", sendBuf, 1024);
		send(socketServer, sendBuf, 1024, 0);

		// 收信息
		// 定义接收服务端信息的缓存区
		char recvBuf[1024] = { 0 };
		int res = recv(socketServer, recvBuf, 1024, 0);
		// 判断是否成功接收到信息
		if (0 == res)
		{
			printf("服务端下线了\n");
			break;
		}
		else if (SOCKET_ERROR == res)
		{
			// 获取错误码
			int error = WSAGetLastError();
			printf("连接服务端失败,返回错误号为:%d", error);
			printf("\n");
			break;
		}
		else
		{
			// 打印信息
			printf("服务端say: %s\n", recvBuf);
		}
	}

	// 关闭套接字
	closesocket(socketServer);
	// 关闭网络库
	WSACleanup();
	system("pause");
	return 0;
}

程序运行结果:

?注:必须先打开服务端,如果是先启动的客户端会出现一下错误:

?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 11:51:07  更:2021-07-24 11:52:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 20:38:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码