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

标签: NetWork(大数据,云计算) NetWork(大数据,云计算)
9人阅读 评论(0) 收藏 举报
分类:
/*-----------------------------------------------------------------

运行该程序相当于启动了服务器,用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    1


TCHAR 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_ERROR
        stFds.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 buffer
            if(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,请检查是否有其它程序在使用!");
     //创建socket
    SOCKET hListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    *(SOCKET*)lpParam = hListenSock;
    //绑定socket
    SOCKADDR_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
BEGIN
    LTEXT           "当前连线的客户端数量:",IDC_STATIC,15,15,89,8
    LTEXT           "0",IDC_COUNT,109,15,44,8

END

resource.h>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

#define IDC_COUNT                       1001




查看评论

深入研究socket编程(1)-----socket之TCP回射服务器/客户端程序

unix环境高级编程-------socket(套接字)中对socket编程有了初步的了解,在本篇以及后续的博客中来深入探讨各种实例以及更多的socket编程技术。 来看一个例子:服务端的se...
  • chenxun2009
  • chenxun2009
  • 2016-01-09 16:06:44
  • 1587

TCP实现ECHO程序(服务端同时处理多个客户端的响应)

一、ECHO意为应答,程序的功能是客户端向服务器发送一个字符串,服务器不做任何处理,直接把字符串返回给客户端,ECHO是自己笨的客户/服务器程序。 二、目前为止我们编写的程序中,服务器只能处理一个客...
  • u014756517
  • u014756517
  • 2016-07-27 09:46:09
  • 1806

Java编写一个简单的TCP通信程序。服务器发送一条字符串,客户端接收该信息并显示。

import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; ...
  • houtaidaima
  • houtaidaima
  • 2016-03-11 16:31:53
  • 5757

TCP-客户端给服务端发送数据,服务端收到后,给客户端反馈信息

import java.io.*; import java.net.*; /*TCP传输2 演示tcp的传输的客户端和服务端的互访需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息. *//...
  • blacop
  • blacop
  • 2016-08-13 23:18:21
  • 3003

服务器编程入门(11)TCP并发回射服务器实现 - 单线程select实现

问题聚焦: 当客户端阻塞于从标准输入接收数据时,将读取不到别的途径发过来的必要信息,如TCP发过来的FIN标志。 因此,进程需要内核一旦发现进程指定的一个或多个IO条件就绪(即输入已准备好被读取,...
  • zs634134578
  • zs634134578
  • 2014-03-31 11:58:40
  • 1447

10、使用TCP协议完成一个客户端一个服务器。客户端从键盘输入读取一个字符串,发送到服务器。 服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。

/**10、使用TCP协议完成一个客户端一个服务器。客户端从键盘输入读取一个字符串,发送到服务器。 服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。    * 客户端*/...
  • u014049880
  • u014049880
  • 2014-05-22 16:12:08
  • 3856

笔试题积累

1,烽火科技笔试题
  • yixiang1989
  • yixiang1989
  • 2014-08-09 19:10:40
  • 868

客户端收到一个窗口为 0 的包怎么处理

转载:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28811518&id=5603324调整窗口大小: 当TCP堆 栈接收到数据的...
  • starstar1992
  • starstar1992
  • 2017-12-05 11:38:44
  • 209

erlang tcp服务器和客户端的简单实现

看了《erlang程序设计》的lib_chan代码,自己也试着写了一个,不过大部分代码都摘自lib...
  • xuxiaolei
  • xuxiaolei
  • 2014-09-21 16:39:08
  • 924

linux socke编程实例:一个简单的echo服务器程序

    也许是第一次真正使用linux操作系统,忽然对丢弃已久的C产生了很大的兴趣,最近想学点linux的知识,在linux的世界里面,接触得最多的还是C,故有感写一下linux的socket程序。 ...
  • linyt
  • linyt
  • 2007-07-31 18:08:00
  • 8514
    个人资料
    等级:
    访问量: 1344
    积分: 790
    排名: 7万+
    文章存档