服务端与客户端1.1——持续处理“单个客户端”发送的请求

上接程序1.0 socket基础api和服务端与客户端1.0_贪睡的蜗牛的博客-CSDN博客 

å¨è¿éæå¥å¾çæè¿°

1、 服务端做的修改

服务端原本为 (1)建立socket (2)绑定端口 (3) 监听端口 (4)等待客户端链接(5)向客户端发送一条数据(6)关闭socket        第四步和第五步处于循环状态  这里向客户端发送完一条数据就会继续的监听,如果有新的客户端来请求就会覆盖原先的连接

现在修改为:(1)建立socket (2)绑定端口 (3) 监听端口 (4)等待客户端链接(5)客户端发送的请求 (6)处理客户端发送的请求 (7)答复客户端的请求 (8)关闭socket    第五步到第七步处于循环状态

改造后将accept移出while循环,那么会持续的对这个连接接收发来的数据

 2、客户端做的修改

 客户端原先为 (1)建立socket (2)连接到服务端 (3)接收服务端发来的消息 (4)关闭socket  没有while循环,接收一次服务端发送来的请求就会关闭

  客户端修改后为 (1)建立socket (2)连接到服务端 (3)发送请求 (4)得到请求结果 (5)关闭socket  3和4是持续的进行

代码

服务端修改后的代码

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<Windows.h>
#include<WinSock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP服务端

	//	1. 建立一个Socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ipv4 面向字节流的 tcp协议

	//	2. 绑定接受客户端连接的端口 bind

	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型
								 //网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = INADDR_ANY; //不限定访问该服务端的IP
	if (bind(_sock, (sockaddr*)&_sin, sizeof(_sin)) == SOCKET_ERROR)  //sockaddr 不利于编码  
	{
		cout << "ERROR: 绑定用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 绑定端口成功..." << endl;
	}
	//	3. 监听网络端口 listen

	if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数 backbag 最大允许连接数量
	{
		cout << "ERROR: 监听用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 监听端口成功..." << endl;
	}

	//	4. 等待接受客户端连接 accept

	sockaddr_in _clientAddr = {};
	int cliendAddrLen = sizeof(_clientAddr);
	SOCKET _clientSock = INVALID_SOCKET; // 初始化无效的socket 用来存储接入的客户端

	_clientSock = accept(_sock, (sockaddr*)&_clientAddr, &cliendAddrLen);

	while (true)
	{
		char _recvBuf[128] = {};
		int nlen = recv(_clientSock, _recvBuf, 128, 0); //接受客户端的数据 第一个参数应该是客户端的socket对象
		if (nlen <= 0)
		{
			//客户端退出
			cout << "客户端已退出,任务结束" << endl;
			break; 
		}
		cout << "收到命令:" << _recvBuf << endl;
		//6 处理请求  这里只是简单的字符串判断
		if (0 == strcmp(_recvBuf, "getName"))
		{
			//	7. 向客户端发送一条数据 send
			char msgBuf[] = "Evila";
			send(_clientSock, msgBuf, strlen(msgBuf) + 1, 0); //+1是为了把\0算进去
		}
		else if (0 == strcmp(_recvBuf, "getAge"))
		{
			//	7. 向客户端发送一条数据 send
			char msgBuf[] = "80";
			send(_clientSock, msgBuf, strlen(msgBuf) + 1, 0); //+1是为了把\0算进去
		}
		else
		{
			//	7. 向客户端发送一条数据 send
			char msgBuf[] = "Hello, I'm Server";
			send(_clientSock, msgBuf, strlen(msgBuf) + 1, 0); //+1是为了把\0算进去
		}
	}

	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	return 0;
}

客户端修改后的代码

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<Windows.h>
#include<WinSock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP客户端

	//	1. 建立一个Socket  下面第三个参数不需要指定
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, 0); // ipv4 面向字节流的 tcp协议
	if (INVALID_SOCKET == _sock)
	{
		cout << "错误,建立socket失败"<<endl;
	}
	else
	{
		cout << "成功建立客户端socket"<<endl;
	}
	//	2. 连接服务器 connect
	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型
								 //网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 

	int ret = connect(_sock, (sockaddr*)&_sin, sizeof(sockaddr_in));
	if (SOCKET_ERROR == ret)
	{
		cout << "错误,connect失败" << endl;
	}
	else
	{
		cout << "成功,connect 成功" << endl;
	}

	//3 接收服务器数据 resv
	char recvBuf[256] = {};
	while (true)
	{
		// 获取请求命令
		char cmdBuf[128] = {};
		cout << "输入命令: ";
		cin >> cmdBuf;

		// 4 处理请求
		if (strcmp(cmdBuf, "exit") == 0)
		{
			break;
		}
		else
		{
			// 5 向服务器发送请求命令
			send(_sock, cmdBuf, strlen(cmdBuf) + 1, 0);
		}
		//放到循环中 重复接受服务器的返回信息
		//6. 接受服务器信息 recv
		char recvBuf[256] = {};
		int nlen = recv(_sock, recvBuf, sizeof(recvBuf), 0); //返回值是接收数据的长度
		if (nlen > 0)
		{
			cout << recvBuf << endl;
		}
		else
		{
			cout << "ERROR: 数据传输失败..." << endl;
		}

	}




	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	getchar();//防止一闪而过
	return 0;
}

 总结

  • 客户端在连接服务端后形成后的socket就是与服务端沟通的桥梁,通过这个socket不断地与服务端send和recv即可实现与服务端的通信
  • 服务端与客户端之间也是通过socket实现提供服务

下接服务端与客户端1.2——发送结构化消息_贪睡的蜗牛的博客-CSDN博客

posted @   贪睡地蜗牛  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示