一个简易TCP服务器的多种实现
来源:互联网 发布:hp1010墨盒清零软件 编辑:程序博客网 时间:2024/05/01 14:56
作为对上一篇文章的相关代码补充点击打开链接
#include "stdafx.h"#include <WinSock2.h>#include <iostream>#include <MSTCPiP.h>//#define BOOST_ALL_DYN_LINK//使用动态库链接#include <boost/thread.hpp>#include <boost/bind.hpp>#include <boost/asio.hpp>#include <boost/smart_ptr.hpp>#pragma comment(lib,"WS2_32.lib")void handle_msg(SOCKET con_socket){if (con_socket == INVALID_SOCKET){return;}char server_text[] = "TCP server demo!";char szMessage[1024] = {0};send(con_socket, server_text, strlen(server_text), 0);int errorcode;while(true){int ret_size = recv(con_socket, szMessage, 1024, 0);if ( (ret_size == 0) || (ret_size == SOCKET_ERROR) ){errorcode = WSAGetLastError();if (errorcode == WSAEWOULDBLOCK){std::cout << "等待接收数据" << std::endl;Sleep(1000);continue;}else{printf("Client has closed the connection\n"); return;}}else{szMessage[ret_size] = '\0';std::cout << boost::this_thread::get_id() << "接收到数据:" << szMessage <<std::endl;}send(con_socket, server_text, strlen(server_text), 0);}}//同步服务器,利用winsock2和ws2_32.lib,利用boost::threadgroup(线程池)实现较为高效的处理,阻塞模式,主线程负责接收客户端的连接请求,子线程负责socket业务通信int SyncSocketSvr() {WSADATA wsaData;//初始化socket环境if(WSAStartup(0x0202, &wsaData) != 0){std::cout << "初始化socket lib环境失败" << std::endl;return -1;}//创建socket,默认是阻塞的SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (listen_sock == INVALID_SOCKET){std::cout << "创建socket失败" << std::endl;return -1;}//将socket设置为非阻塞模式int iMode = 1; //0:阻塞if (ioctlsocket(listen_sock, FIONBIO, (u_long FAR*) &iMode) == SOCKET_ERROR)//非阻塞设置{std::cout << "set asyn I/O失败!" << std::endl;return -1;}//初始化服务器的IP地址sockaddr_in server_addr;memset(&server_addr, 0, sizeof(sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(2000);//绑定IP到socket上if(bind(listen_sock, (LPSOCKADDR)&server_addr, sizeof(server_addr)) == SOCKET_ERROR){std::cout << "bind failed!" << std::endl;return -1;}//开启监听if (listen(listen_sock, 3) == SOCKET_ERROR){std::cout << "listen failed" << std::endl;}//循环接收客户端的连接请求sockaddr_in remote_addr;memset(&remote_addr, 0, sizeof(sockaddr_in));int addr_len = sizeof(sockaddr_in);SOCKET connect_sock;char server_text[] = "TCP server demo!";boost::thread_group tg;int errorcode;fd_set listen_set;timeval time_out;while(true){FD_ZERO(&listen_set);//初始化set集合FD_SET(listen_sock, &listen_set);//设置set集合time_out.tv_sec = 1;time_out.tv_usec = 0;int ret = select(0, &listen_set, NULL, NULL, &time_out);if (ret <= 0){if (ret < 0){std::cout << "监听时select返回错误:" << WSAGetLastError() << std::endl;}elsecontinue;//超时}if (FD_ISSET(listen_sock, &listen_set))//listen_sock是不是有可读数据{connect_sock = accept(listen_sock, (LPSOCKADDR)&remote_addr, &addr_len);if (connect_sock == INVALID_SOCKET){errorcode = WSAGetLastError();if (errorcode == WSAEWOULDBLOCK)//表示没有客户端发起连接,继续循环 {Sleep(100);continue;}else{std::cout << "connect failed!" << std::endl;return -1;}}//将socket设置为非阻塞模式int con_Mode = 1; //0:阻塞if (ioctlsocket(connect_sock, FIONBIO, (u_long FAR*) &con_Mode) == SOCKET_ERROR)//非阻塞设置{std::cout << "set asyn I/O失败!" << std::endl;return -1;}std::cout << "接收到一个连接请求,IP:" << inet_ntoa(remote_addr.sin_addr) << std::endl;//主流做法:创建一个子线程,绑定这个socket,负责此socket上的所有通信,或者采用线程池tg.create_thread(boost::bind(handle_msg, connect_sock));}}tg.join_all();//关闭连接,延时5秒直接关闭,原来的closesocket后,socket处于time_wait状态,不能立即复用,下面的方法是等待5秒后,直接释放可以复用//SO_LINGER将决定系统如何处理残存在套接字发送队列中的数据struct linger{u_short l_onoff;u_short l_linger;};linger m_linger;m_linger.l_onoff = 1;m_linger.l_linger = 5;//若为0,直接丢弃setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (const char*)&m_linger, sizeof(m_linger));//setsockopt(listen_sock, SOL_SOCKET, SO_DONTLINGER, (const char*)&m_linger, sizeof(m_linger));closesocket(listen_sock);WSACleanup();return 0;}
0 0
- 一个简易TCP服务器的多种实现
- JAVA模拟客户机与服务器实现简易的TCP通讯
- 实现一个同步的迭代型TCP服务器
- [java网络编程]一个简易网络服务器的实现
- 一个简易的http服务器。
- Qt:简易的TCP服务器和客户端
- 简易HTTP服务器的实现
- 用IOCP实现个简易TCP并发服务器
- 用Reactor框架实现一个简单的tcp服务器
- 实现一个同步的并发型TCP服务器
- 基于BIO的TCP编程简易实现
- 一个简易计算器的实现
- 一个简易的libevent实现
- 一个简易JVM的实现
- 一个简易的WebServer实现
- 实现一个简易的电子钟
- 【JavaWeb】一个简易的服务器类
- 一个支持 cgi 的简易 http 服务器
- ajaxFileupload只能选择一个文件问题解决
- UIBezierPath贝塞尔曲线的常用方法总结
- 系统学习机器学习之模型选择
- Maven 整合 SpringMvc Spring Hibernate +oracle
- java List系(ArrayList,LinkedList,Vector)的比较
- 一个简易TCP服务器的多种实现
- vs2010 如何快速查看 别人工程代码
- 用Spark实现K-means(scala:面向函数式编程风格)
- java上传文件跟批量下载文件
- Android 基于Message的进程间通信
- C++入门(20):字符串
- AutoCompleteTextView的简单使用
- nodejs-post文件上传原理详解
- WebDriverWait