|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
- // Echo服务器 :
- // 客户端给服务器发来的信息,服务器原封不动的还给客户端。作用:保证服务器可以完
- // 整的收到客户端的消息包,并且能把客户端的信息完整的会给客户端,确认两边通信是没有问题的
- // 消息包:可以打上时间戳。包的长度两边都是不知道的
- // 我另外加入了一条逻辑,当有新的客户端进入后,先发送一条当前时间的消息给客户端;
- // 再开始原封不动的把客户端发来的消息还给客户端
- #include <boost/asio.hpp>
- #include <utility>
- #include <iostream>
- #include <string>
- using boost::asio::ip::tcp;
- std::string make_daytime_string()
- {
- using namespace std;//For time_t, time and ctime;
- //time_t now = time(0);
- auto now = time(nullptr);
- return ctime(&now); // 返回const char*
- }
- // session是智能指针管理方法,从public std::enable_shared_from_this<session>派生出来就意
- // 味着自身是一个智能指针
- class session : public std::enable_shared_from_this<session>
- {
- public:
- session(tcp::socket socket) : socket_(std::move(socket))
- {
- // start();
- // do_read();
- // 如果写了start()或者do_read(),就调用了shared_from_this(),但是这个时候自身构造还没有完毕,还在
- //构造函数里,没有出构造这个圈子,这个时候调用shared_from_this()是没办法通过自身来构造
- //shared_from_this的,构造没完成,new就没完成,自己就还不是智能指针呢,所以public
- //std::enable_shared_from_this<session>的派生类不能在构造函数和析构函数调用
- //shared_from_this(),这个是它的局限性。
- }
- void start()
- {
- first_msg();
- }
- private:
- // 另外加的逻辑,先发送一条消息给客户端;
- void first_msg()
- {
- message_ = make_daytime_string();//返回当前时间
- auto self = shared_from_this();
- boost::asio::async_write(
- socket_,
- boost::asio::buffer(message_),
- [self = std::move(self)](const boost::system::error_code & error, std::size_t length){
- self->do_read(error);
- std::cout << "send first msg..." << std::endl;
- });
- }
- void do_read(const boost::system::error_code & error)
- {
- if (!error) {
- // 等待客户端信息的传来
- // 拷贝,引用计数加1,shared_from_this()是右值
- auto self(shared_from_this());
- //发出一个事件,收到一点数据也可以,读一些客户端传来的信息,存到data数组里,最
- //大长度1024,self传入进来的作用是做一个拷贝,拷贝后,它的声明周期和lambda的是一样长的,
- //引用计数加1
- socket_.async_read_some(
- boost::asio::buffer(data_, max_length),
- [this, self](boost::system::error_code ec, std::size_t length)
- {
- if (!ec)
- {
- do_write(ec, length);//写数据给客户端
- }
- });
- }
- else
- {
- std::cout << "in do_read error" << std::endl;
- }
- }
- //收到什么信息就写回去
- void do_write(const boost::system::error_code & error, std::size_t length)
- {
- if (!error) {
- auto self(shared_from_this());
- boost::asio::async_write(
- socket_, boost::asio::buffer(data_, length),
- [this, self](boost::system::error_code ec, std::size_t length)
- {
- if (!ec)
- {
- do_read(ec);
- }
- });
- }
- else
- {
- std::cout << "in do_write error" << std::endl;
- }
- }
- tcp::socket socket_;
- enum { max_length = 1024 };
- char data_[max_length];
- std::string message_;
- };
- class server
- {
- public:
- server(boost::asio::io_service &io_service, short port) :
- acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
- socket_(io_service)
- {
- //do_accept();//在构造函数里把资源构造好就可以了,不要去做事情,做的事情移到外面来
- }
- //提供一个外部函数,没有必要构造好就立即工作,可以在某个时机调用
- void start()
- {
- do_accept();
- }
- private:
- //接收客户端,对客户端进行构造,调用start,接着接收下一个客户端
- void do_accept() //异步接收客户端的连接
- {
- acceptor_.async_accept(socket_, [this](boost::system::error_code ec)
- {
- if (!ec)
- {
- //move操作过后,socket相当于还是socket_(io_service)这种状态.
- auto newSession = std::make_shared<session>(std::move(socket_));
- newSession->start();
- }//session当成一个客户端
- do_accept();//不管错没错都接着接收客户端
- });
- }
- tcp::acceptor acceptor_;//监听端口号,连接新的客户端
- tcp::socket socket_;
- };
- int main()
- {
- // 我们的程序和操作系统底层之间的一个相互传递的枢纽
- // 会把事件按照一定方式进行处理;
- boost::asio::io_service io;
- try
- {
- server s(io, 2001);
- s.start();
- io.run();
- }
- catch (std::exception &e)
- {
- std::cerr << e.what() << std::endl;
- }
- std::cout << "mian finish run \n" << std::endl;// 提示下main函数已经结束了
- system("pause");// 让VS控制台程序不会一闪而过;
- return 0;
- }
复制代码
//move完后,原先的值是未定义的状态,相当于是被初始化了。
- class ObjectWithMove {
- public:
- ObjectWithMove(int a) : m_a(a), m_p(p) {}
- ObjectWithMove(ObjectWithMove&& lhs) : m_a(lhs.m_a), m_p(lhs.m_p) {
- lhs.m_a = 0;
- lhs.m_p = nullptr;
- }
- private:
- int m_a;
- int *m_p;
- };
复制代码
用C#写了个简单的客户端来测试:
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.Text;
- using System;
- public class Test002 {
-
- private static byte[] result = new byte[1024];
-
- int main () {
-
- //设定服务器IP地址
- IPAddress ip = IPAddress.Parse("127.0.0.1");
- Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- try
- {
- clientSocket.Connect(new IPEndPoint(ip, 2001)); //配置服务器IP与端口
- Console.WriteLine("连接服务器成功");
- }
- catch
- {
- Console.WriteLine("连接服务器失败,请按回车键退出!");
- return;
- }
- //通过clientSocket接收数据
- int receiveLength = clientSocket.Receive(result);
- Console.WriteLine("接收服务器消息:"+Encoding.ASCII.GetString(result,0,receiveLength));
- //通过 clientSocket 发送数据
- for (int i = 0; i < 3; i++)
- {
- try
- {
- Thread.Sleep(1000); //等待1秒钟
- string sendMessage = "client send Message Hellp" + DateTime.Now;
- clientSocket.Send(Encoding.ASCII.GetBytes(sendMessage));
- Console.WriteLine("向服务器发送消息:" + sendMessage);
-
- receiveLength = clientSocket.Receive(result);
- Console.WriteLine("接收服务器消息:"+Encoding.ASCII.GetString(result,0,receiveLength));
- }
- catch
- {
- Console.WriteLine("与服务器断开连接");
- clientSocket.Shutdown(SocketShutdown.Both);
- clientSocket.Close();
- break;
- }
- }
- Console.WriteLine("发送完毕,按回车键退出");
-
- }
-
- }
复制代码
对应的C++客户端在下一篇研究 |
评分
-
查看全部评分
|