boost asio库单线程异步发送乱序 贴代码.....
时间:2010-09-01
来源:互联网
- #include <iostream>
- #include <istream>
- #include <ostream>
- #include <fstream>
- #include <string>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <deque>
- #include <queue>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <boost/noncopyable.hpp>
- #include <boost/thread.hpp>
- #include <boost/lexical_cast.hpp>
- #include <boost/shared_ptr.hpp>
-
- using boost::asio::ip::tcp;
- /**
- * * @brief 发送数据解构体
- * */
- struct SSendDataBuff
- {
- SSendDataBuff(const char *s, size_t n) : pData(NULL), nSize(0)
- {
- pData = new char[n];
- memset(pData, 0, n);
- memcpy(pData, s, n);
- nSize = n;
- }
-
- ~SSendDataBuff()
- {
- if(pData)
- {
- delete [] pData;
- pData = NULL;
- }
- nSize = 0;
- }
-
- char *pData; //数据
- size_t nSize; //数据长度
- };
- class client
- {
- public:
- client(boost::asio::io_service& io_service)
- :socket_(io_service), resolver(io_service)//, m_io_work(io_service)
- {
- m_bHasSend = true;
- tcp::resolver::query query("192.168.0.226", "9988");
- tcp::resolver::iterator iterator = resolver.resolve(query);
-
- tcp::endpoint endpoint = *iterator;
- socket_.async_connect(endpoint,
- boost::bind(&client::__handle_connect, this,
- boost::asio::placeholders::error));
- }
- void __handle_connect(const boost::system::error_code& err)
- {
- if(err) //连接失败
- {
- printf("Connect is faild ....\n");
- }
- {
- printf("Connect is Successful ....\n");
- FILE *pt = fopen("./libs", "rb");
- if(NULL == pt)
- {
- assert(0);
- }
-
- char buff[1024];
- int nLen = 0;
- memset(buff, 0, sizeof(buff));
- while((nLen = fread(buff, sizeof(char), sizeof(buff), pt)) != 0)
- {
- sends(buff, nLen);
- memset(buff, 0, sizeof(buff));
- }
- printf("===============\n");
- fclose(pt);
- }
- }
- void sends(const char *pData, size_t nSize)
- {
- boost::mutex::scoped_lock AsynSendlock(m_SendQueMutex);
- if(m_bHasSend) //可以直接发送不需要放到缓冲区
- {
- __asynSendData(pData, nSize);
- m_bHasSend = false;
- }
- else
- {
- SSendDataBuff *pSendDataBuffer = new SSendDataBuff(pData, nSize);
- m_AsynSendQue.push(pSendDataBuffer);
- }
- }
- void __asynSendData(const char *pData, size_t nSize)
- {
- #if 0
- static FILE *pt = fopen("./TEST_WRITE", "wb");
- if(NULL == pt)
- {
- assert(0);
- }
-
- size_t nLen = fwrite(pData, sizeof(char), nSize, pt);
- if(nLen != nSize)
- {
- assert(0);
- }
- fflush(pt);
- #endif
-
- async_write(socket_, boost::asio::buffer(pData, nSize),
- boost::bind(&client::__handle_tcp_write, this,
- boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
- }
- void __handle_tcp_write(const boost::system::error_code& e, size_t nSize)
- {
- printf("__handle_tcp_write ... nSize = %d\n", nSize);
- if(e) //写错误
- {
- assert(0);
- return;
- }
-
- boost::mutex::scoped_lock AsynSendlock(m_SendQueMutex);
- if(!m_AsynSendQue.empty()) //如果发送队列不为空发送数据
- {
- SSendDataBuff *p = m_AsynSendQue.front();
- __asynSendData(p->pData, p->nSize);
- delete p;
- p = NULL;
-
- //清除
- m_AsynSendQue.pop();
- }
- else
- {
- m_bHasSend = true;
- }
- }
- private:
- tcp::socket socket_;
- tcp::resolver resolver;
- //boost::asio::io_service::work m_io_work;
-
- volatile bool m_bHasSend; //标识数据是否直接发送还是放到缓冲区
- std::queue<SSendDataBuff *> m_AsynSendQue; //保存异步发送数据队列
- boost::mutex m_SendQueMutex; //异步发送数据队列锁
- };
-
- int main(int argc, char* argv[])
- {
- system("rm -rf TEST_WRITE");
- try
- {
- boost::asio::io_service io_service;
- client c(io_service);
- io_service.run();
- printf("HELLO ........\n");
- }
- catch (std::exception& e)
- {
- std::cout << "Exception: " << e.what() << "\n";
- }
-
- return 0;
- }
服务器代码如下, 非常简单的一个原始套接口
- #include <assert.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <iostream>
- #include <sstream>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-
- int Bind(const char *ip, unsigned int nPort)
- {
- int nSockfd = ::socket(PF_INET, SOCK_STREAM, 0);
- if(-1 == nSockfd)
- {
- assert(0);
- }
- //解构体初始化
- struct sockaddr_in servaddr;
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = PF_INET;
- if(NULL == ip)
- {
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- }
- else
- {
- int nRet = inet_pton(PF_INET, ip, &servaddr.sin_addr);
- if(-1 == nRet)
- {
- assert(0);
- }
- }
- servaddr.sin_port = htons(nPort);
-
- int nRet = ::bind(nSockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
- if(-1 == nRet)
- {
- assert(0);
- }
-
- nRet = ::listen(nSockfd, 256);
- if(-1 == nRet)
- {
- assert(0);
- }
- return nSockfd;
- }
-
- int main()
- {
- system("rm -rf TEST_WRITE");
- int nSockfd = Bind("192.168.0.226", 9988);
- int nClientSockfd = 0;
- while(1)
- {
- nClientSockfd = ::accept(nSockfd, NULL, NULL);
- if(-1 == nClientSockfd)
- {
- if(errno == EINTR)
- {
- continue;
- }
- return -1;
- }
- else
- {
- printf("new Client .........\n");
- break;
- }
- }
- while(1)
- {
- char buff[65535];
- int nLen = recv(nClientSockfd, buff, sizeof(buff), 0);
- if(-1 == nLen)
- {
- assert(0);
- }
-
- static FILE *pt = fopen("./TEST_WRITE", "wb");
- if(NULL == pt)
- {
- assert(0);
- }
-
- size_t n = fwrite(buff, sizeof(char), nLen, pt);
- if(n != nLen)
- {
- assert(0);
- }
- fflush(pt);
- }
-
- return 0;
- }
作者: ruchong 发布时间: 2010-09-01
难道大家都没有用boost吗....大家帮帮忙 ...
多谢....
多谢....
作者: ruchong 发布时间: 2010-09-02
本帖最后由 ideawu 于 2010-09-02 17:38 编辑
不要在sends里把消息加入队列, 直接调用异步发送就行了。
不要在sends里把消息加入队列, 直接调用异步发送就行了。
作者: ideawu 发布时间: 2010-09-02
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28