/*-----------------------------------------------------------------运行该程序相当于启动了服务器,用telnet客户端来连接服务器。命令:telnet 127.0.0.1 9999
-----------------------------------------------------------------*/
#include <Windows.h>
#include "resource.h"
#include  <process.h>#pragma comment(lib,"Ws2_32.lib")#define TCP_PORT  9999  //监听端口
#define F_STOP    1TCHAR szAppName[] = TEXT("TcpEcho");
int g_iThreadCount = 0;
HWND hWnd = NULL; //对话框句柄
int g_dwFlag=0; //退出标志BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{DialogBox(hInstance, TEXT("TCPECHO"), NULL, DlgProc);return 0;
}//通信服务线程,每个客户端登录的连接将产生一个线程
unsigned int WINAPI ServiceThread(void* lpParam){SOCKET hSrvSock = (SOCKET)lpParam;char szBuff[512];int iRet;FD_SET stFds; TIMEVAL stTv;//WaitFor Socket++g_iThreadCount;SetDlgItemInt(hWnd, IDC_COUNT, g_iThreadCount, FALSE);while(!(g_dwFlag & F_STOP)){//select函数用于判断套接字是否有可读、可读或是否有异常//如果检测的就绪时,会返回就数据套接字的数量//如果因超时而返回时,返回值是0//如果因异常(如连接断开)时,返回SOCKET_ERRORstFds.fd_count = 1; stFds.fd_array[0] = hSrvSock;stTv.tv_sec = 0; stTv.tv_usec = 200 * 1000;//200ms;//因默认recv和send是阻塞的,用该函数来检测//当套接字可读或可写时再去recv或send以防止//该线程被阻塞。因为一旦被阻塞,当用户关闭//应用程序时,g_dwFlag退出标志就无法被检测到,//而如果客户端没发送数据时,会使该线程//无法退出。所以用select加以检测。iRet = select(0, &stFds, NULL, NULL, &stTv);if(SOCKET_ERROR == iRet)            break;if(iRet){memset(szBuff, 0, sizeof(char)*512);//clear bufferif(SOCKET_ERROR == recv(hSrvSock, szBuff, sizeof(szBuff), 0))        break;if(SOCKET_ERROR == send(hSrvSock, szBuff, iRet, 0))                        break;}}closesocket(hSrvSock);--g_iThreadCount;SetDlgItemInt(hWnd, IDC_COUNT, g_iThreadCount, FALSE);return TRUE;
}//监听线程
unsigned int  WINAPI ListenThread(void* lpParam){TCHAR szErrBind[]  = TEXT("无法绑定到TCP端口9999,请检查是否有其它程序在使用!");//创建socketSOCKET hListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);*(SOCKET*)lpParam = hListenSock;//绑定socketSOCKADDR_IN stSA; memset(&stSA, 0, sizeof(SOCKADDR_IN));stSA.sin_port = htons(9999); stSA.sin_family = AF_INET; stSA.sin_addr.S_un.S_addr = INADDR_ANY;if(bind(hListenSock, (PSOCKADDR)&stSA, sizeof(SOCKADDR_IN))){//返回0表示无错误,是成功的。MessageBox(hWnd, szErrBind, szAppName, MB_OK|MB_ICONSTOP);closesocket(hListenSock);return FALSE;}//开始监听,等待连接并为每个连接创建一个新的服务线程listen(hListenSock, 5);while(TRUE){SOCKET hServiceSock = accept(hListenSock, NULL, 0);if(hServiceSock == INVALID_SOCKET)        break;unsigned int dwThreadId;HANDLE hServiceThread = (HANDLE)_beginthreadex(NULL, 0, &ServiceThread, (LPVOID)(hServiceSock), 0, &dwThreadId);CloseHandle(hServiceThread);//线程是内核对象,关闭表示不需用操作了(如唤醒、挂机)。}closesocket(hListenSock);return TRUE;
}BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{WSADATA stWSA;static SOCKET hListenSocket = NULL;static HANDLE hListenThread = NULL;switch (message){case WM_INITDIALOG:hWnd = hwnd;//载入WS2_32.DLL动态链0x0002:MAKEWORD(2,0)WSAStartup(MAKEWORD(2,0), &stWSA);//动态库的信息返回到WSAdata变量中//创建监听线程unsigned int dwThreadId;hListenThread = (HANDLE)_beginthreadex(NULL, 0, &ListenThread, (LPVOID)(&hListenSocket), 0, &dwThreadId);//只是关闭了一个线程句柄对象,表示我不再使用该句柄,即不对这个句柄对//应的线程做任何干预了(如挂起或唤醒)。并没有结束线程。CloseHandle(hListenThread);                     return TRUE;case WM_CLOSE://当未有客户端连接时,该socket在线程中创建,且未退出线程。//所以要在这里监听socket,此时会将accept返回失败,监听线程退出。closesocket(hListenSocket);g_dwFlag |= F_STOP;   //设置退出标志,以便让服务线程中止      while (g_iThreadCount > 0); //等待服务线程关闭WSACleanup();EndDialog(hwnd, 0);return TRUE;}return FALSE;}rc>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>TCPECHO DIALOGEX 0, 0, 165, 36
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "TcpEcho服务器"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGINLTEXT           "当前连线的客户端数量:",IDC_STATIC,15,15,89,8LTEXT           "0",IDC_COUNT,109,15,44,8ENDresource.h>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>#define IDC_COUNT                       1001

一个简易的TCP服务器程序(将收到的字符发回给客户端)相关推荐

  1. go高性能tcp服务器,MarioTCP: Multi Libvent TCP Server 一个高性能的TCP服务器

    我在sourceforge上建了这个开源项目,把项目介绍首发在csdn:http://blog.csdn.net/everlastinging/article/details/10894493 没想到 ...

  2. Python简易web静态服务器程序搭建

    Python简易web静态服务器程序搭建 Python自带简易静态web服务器搭建 http.server模块 DIY简易静态web服务器程序搭建 普通版 步骤 具体代码 面向对象版 代码 命令行版 ...

  3. 快速搭建一个简易的HTTP服务器用于文件分享与下载

    需要快速搭建一个简易的HTTP服务器进行文件的分享与下载.主要有以下两种方法: 1. 使用python 来实现 import http.server import socketserverPORT = ...

  4. Python写一个简易的web服务器

    Greg Wilson是Software Carpentry(为科学家和工程师提供在计算技能方面的速成课程)的创始人.他已经在学术界和工业界工作了30年,是几本计算方面的书,包括获得2008年jolt ...

  5. MFC调用winhttp实现简易的HTTP服务器程序

    Windows提供的winhttp函数库用来快速实现HTTP协议的应用程序,包括客户端和服务器端. 服务器开发一般流程是这样的: 1.HttpInitialize 初始化WinHTTP函数库: 2.H ...

  6. (C#)一个简易的水准网平差程序

    这是用C#链表写的一个简易的水准网按测距平差的窗体程序. 这是运行的窗体界面: 读取的数据格式为:点号,高差,测距.例如: 得出的运行结果如下: 下面就是我的具体代码: using System; u ...

  7. 一个简单的TCP服务器

    1.只接收一个连接然后自动关闭的服务端代码 1 -module(socket_server). 2 3 -export([start_nano_server/0]). 4 5 start_nano_s ...

  8. python -m http.server 搭建一个简易web下载服务器(可用于快速发送大文件)

    在工作过程中需要经常发送安装包等大文件给同事,亲测共享文件夹拷贝.QQ.微信等聊天工具,大文件传输速度效率不高. 然而局域网内使用python搭建的简易下载服务器速度比较快,百兆网卡下载速度随便达到1 ...

  9. 用java的二维数组做一个简易计算优惠小程序(附带源码)

    要求: 1.单点: 溜肥肠24元 酱肘子32 米饭3元 2.订单满30打八折 3.优惠价: 溜肥肠18元 4.打八折与优惠价不能同时使用,点这三样,最少多少钱? 思路: 首先定义一个 String 类 ...

最新文章

  1. 在OpenCV中使用单应性进行姿势估计
  2. KMP----next数组 最长相同前后缀 递归求法解释
  3. 只需两步,Tomcat JVM 参数性能迅速调到最优!
  4. 03-JDBC连接MySQL数据库【插入数据】
  5. HP前女老板Dunn和Carly的琐碎事
  6. 图书管理销售系统需求分析报告,对性能的规定以及运行环境规定部分
  7. empty()、isset()、is_null()的区别
  8. 【报告分享】新零售专题报告:从直播电商的春秋战国,看mcn的进阶之道.pdf
  9. li鼠标悬浮手势样式
  10. linux清除占用端口,Linux中解除端口占用的方法
  11. soapUI接口测试工具
  12. tomcat优化问题
  13. 【模电】0010 正弦波产生电路(RC正弦波振荡电路)
  14. 谷歌学术高级搜索技巧
  15. 处理:TF卡突然变成8M,格式化提示写保护
  16. matlab中指数信号,Matlab入门篇——正弦信号、实指数信号和复指数信号仿真.ppt...
  17. L1-009 N个数求和(解决测试点三错误)
  18. OOC-GCC 特性介绍
  19. 100个RPA经典应用场景解析
  20. VSCode lua插件LuaHelper

热门文章

  1. js判断两个数组是否相同
  2. 深度学习论文笔记(可解释性)——CAM与Grad-CAM
  3. 广东石油化工学院计算机基础,广东石油化工学院计算机基础答案
  4. 如何加载HTML页面页面到另一个界面中
  5. 从一个页跳到另一个页面,另一个页面检查第一个页面的信息。
  6. 计算机一级考试文字处理题知识
  7. python+django 实现从服务器下载pdf文档的功能
  8. 书法练字帖纸——井字格获得国家知识产权局专利证书
  9. 今年劳动节放假为何调整
  10. libvlc获取一帧_android - 从android vlc媒体播放器获取当前帧 - 堆栈内存溢出