zoukankan      html  css  js  c++  java
  • windows下socket学习(一)

    关于socket的文章,园子里面有很多,其实无非就是 WSAStartup、socket、bind、listen、accept、recv、send(服务端),WSAStartup、socket、connect、send、recv(客户端)的使用。今天第一次看socket,也只学会了socket阻塞模式,即一个服务端对一个客户端,别的客户端想连接也连接不上--个人理解,不知道对不对。

    为了解决一(服务端)对多(客户端)的问题,自作聪明在服务端用上了多线程。初步效果还不错:

    我晕,1080P的笔记本上截的图,放上来这么大!

    上代码,

    TCPServer.cpp

      1 /****************************************************************************
      2 /*    文 件 名:server.cpp                                                    *
      3 /*    作    者:ZhangXuliang                                                    *
      4 /*    日    期:2015/05/24  星期日  11:28                                        *
      5 /*    版 本 号:V 1.0.0                                                        *
      6 /*    版权说明:Copyright(c)2015 ZXL. All rights reserved.                    *
      7 /*    描    述:多线程处理Client连接                                            *
      8 /****************************************************************************/
      9 
     10 #define _CRT_SECURE_NO_WARNINGS
     11 
     12 #include <iostream>
     13 #include <windows.h>
     14 #include <process.h>
     15 
     16 //#include <WinSock2.h>
     17 #pragma comment(lib,"Ws2_32.lib")
     18 
     19 #define SERVER_IP        "127.0.0.1"
     20 #define SERVER_PORT        9999
     21 #define BUFSIZE            (1024)
     22 
     23 //定义一个结构体,存储客户端的sClient、sockaddr_in结构
     24 typedef struct  _ClientStruct
     25 {
     26     SOCKET csSocket;
     27     SOCKADDR_IN csSockAddr_In;
     28 } ClientStruct, *LPClientStruct;
     29 
     30 //处理后续客户端事件的程序
     31 void ClientEven(PVOID param);
     32 
     33 using namespace std;
     34 int main()
     35 {
     36     int ErrCode;    //错误代码
     37     int addrlen;
     38     WSADATA WSAdata;
     39     SOCKET sServer, sClient;
     40     SOCKADDR_IN saServer, saClient;
     41 
     42     //初始化
     43     ErrCode = WSAStartup(MAKEWORD(2, 2), &WSAdata);
     44     if (ErrCode)
     45     {
     46         cout << "WSAStartup()出错!错误代码:#" << ErrCode << endl;
     47         WSACleanup();
     48         return -1;
     49     }
     50 
     51     //创建套接字
     52     sServer = socket(AF_INET, SOCK_STREAM,0);
     53     if (INVALID_SOCKET == sServer)
     54     {
     55         cout << "socket()出错!错误代码:#" << WSAGetLastError() << endl;
     56         WSACleanup();
     57         return -2;
     58     }
     59 
     60     //初始化saServer
     61     saServer.sin_family = AF_INET;
     62     saServer.sin_addr.S_un.S_addr = htons(INADDR_ANY);
     63     saServer.sin_port = htons(SERVER_PORT);
     64     //绑定监听IP和端口,以便下面的listen()监听
     65     ErrCode = bind(sServer, (SOCKADDR *)&saServer, sizeof(SOCKADDR_IN));
     66     if (SOCKET_ERROR == ErrCode)
     67     {
     68         cout << "bind()出错!错误代码:#" << WSAGetLastError() << endl;
     69         WSACleanup();
     70         return -3;
     71     }
     72 
     73     //开始监听
     74     ErrCode = listen(sServer, 10);
     75     if (SOCKET_ERROR == ErrCode)
     76     {
     77         cout << "listen()出错!错误代码:#" << WSAGetLastError() << endl;
     78         WSACleanup();
     79         return -4;
     80     }
     81     cout << "正在监听端口:" << SERVER_PORT << endl;
     82 
     83     while (TRUE)
     84     {
     85         //接受来自客户端的连接请求
     86         addrlen = sizeof(saClient);
     87         sClient = accept(sServer, (SOCKADDR *)&saClient, &addrlen);
     88         if (INVALID_SOCKET == sClient)
     89         {
     90             cout << "accpet()出错!错误代码:#" << WSAGetLastError() << endl;
     91         }
     92 
     93         //启动一个线程,来处理后续的客户端事件
     94         LPClientStruct lpcsClient = new ClientStruct;    //个人觉得这儿用 new 是一个创举啊,因为在启动线程后,如果直接将ClientStruct指针
     95         lpcsClient->csSocket = sClient;            //传到ClientEven()中,那么,当有中一个Client接入时,会改变ClientEven中的ClientStruct内容
     96         lpcsClient->csSockAddr_In = saClient;        //所以这儿用new,再在线程中delete
     97         _beginthread(ClientEven,0, lpcsClient);        
     98         
     99     }
    100     WSACleanup();
    101     return 0;
    102 }
    103 
    104 
    105 void ClientEven(PVOID param)
    106 {
    107     int ErrCode;
    108 
    109     char buf[BUFSIZE] = { 0 };
    110     SYSTEMTIME time;
    111     GetLocalTime(&time);
    112     sprintf(buf, "%4d-%02d-%02d %02d:%02d:%02d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);
    113     
    114     //设置下输出的字体的颜色
    115     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    116     SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
    117     cout << buf << "	" << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":"
    118         << ((LPClientStruct)param)->csSockAddr_In.sin_port << "	接入服务器" << endl;
    119     //还原字体颜色
    120     SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
    121     //连接成功,先发送一条成功的消息
    122     ErrCode = send(((LPClientStruct)param)->csSocket, "连接服务器成功", strlen("连接到服务器成功!"),0);
    123     if (SOCKET_ERROR == ErrCode)
    124     {
    125         cout << "send()出错!错误代码:#" << WSAGetLastError() << endl;
    126         delete (LPClientStruct)param;
    127         _endthread();
    128     }
    129 
    130     while (TRUE)
    131     {
    132         //接受消息
    133         ZeroMemory(buf, BUFSIZE);
    134         ErrCode = recv(((LPClientStruct)param)->csSocket, buf, sizeof(buf), 0);
    135         if (SOCKET_ERROR == ErrCode)
    136         {
    137             if (WSAGetLastError() == 10054)
    138             {
    139                 SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
    140                 cout << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":" << ((LPClientStruct)param)->csSockAddr_In.sin_port << "	被强制断开连接!" << endl;
    141                 SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
    142             }
    143             else
    144             {
    145                 cout << "recv()出错!错误代码:#" << WSAGetLastError() << endl;
    146             }
    147 
    148             delete (LPClientStruct)param;    //退出线程之前先delete前面new的ClientStruct
    149             _endthread();
    150         }
    151 
    152         cout << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":" << ((LPClientStruct)param)->csSockAddr_In.sin_port << "	说:" << buf << endl;
    153 
    154         //反馈消息                
    155         //if ((pPipe = _popen(buf, "rt")) != NULL)
    156         //{
    157         //    while (!feof(pPipe))
    158         //    {
    159         //        fgets(szResult, 32, pPipe);
    160         //        strcat(buf, szResult);
    161         //        if (strlen(buf) == 1024)
    162         //        {
    163         //            buf[1024] = 'c';    //c --continue
    164         //            send(((LPClientStruct)param)->csSocket, buf, sizeof(buf), 0);
    165         //            ZeroMemory(buf, BUFSIZE);
    166         //        }
    167         //    }
    168         //    _pclose(pPipe);
    169         //}
    170         //else
    171         //    strcpy(buf, "打开匿名管道失败!");
    172 
    173         ErrCode = send(((LPClientStruct)param)->csSocket, buf, sizeof(buf), 0);
    174         
    175         if (SOCKET_ERROR == ErrCode)
    176         {
    177             cout << "send()出错!错误代码:#" << WSAGetLastError() << endl;
    178 
    179             delete (LPClientStruct)param;    //退出线程之前先delete前面new的ClientStruct
    180             _endthread();
    181         }
    182     }
    183     delete (LPClientStruct)param;    //退出线程之前先delete前面new的ClientStruct
    184     _endthread();
    185 }

    下面是TCPClient.cpp

      1 /****************************************************************************
      2 /*    文 件 名:Client.cpp                                                    *
      3 /*    作    者:ZhangXuliang                                                    *
      4 /*    日    期:2015/05/23  星期六  23:30                                        *
      5 /*    版 本 号:V 1.0.0                                                        *
      6 /*    版权说明:Copyright(c)2015 ZXL. All rights reserved.                    *
      7 /*    描    述:Client客户端                                                    *
      8 /****************************************************************************/
      9 
     10 #define _CRT_SECURE_NO_WARNINGS
     11 
     12 #include <iostream>
     13 #include <string>
     14 
     15 #include <winsock.h>
     16 #pragma comment(lib,"ws2_32.lib")
     17 
     18 using namespace std;
     19 
     20 #define BUFSIZE        1024
     21 #define PORT        9999
     22 //#define SERVER_IP    "127.0.0.1"
     23 
     24 int main()
     25 {
     26     WSAData wsaData;
     27     SOCKET sHost;
     28     sockaddr_in addrServ;
     29     char buf[BUFSIZE];
     30     int retVal;
     31 
     32     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
     33     {
     34         cout << "WSAStartup()失败!" << endl;
     35         return -1;
     36     }
     37 
     38     sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     39     if (INVALID_SOCKET == sHost)
     40     {
     41         cout << "socket()出错!" << endl;
     42         WSACleanup();
     43         return -1;
     44     }
     45 
     46     addrServ.sin_family = AF_INET;
     47     addrServ.sin_port = htons(PORT);
     48     addrServ.sin_addr.S_un.S_addr = inet_addr("192.168.1.223");
     49 
     50     retVal = connect(sHost, (LPSOCKADDR)&addrServ, sizeof(addrServ));
     51     if (SOCKET_ERROR == retVal)
     52     {
     53         cout << "connect()出错!" << endl;
     54         closesocket(sHost);
     55         WSACleanup();
     56         return -1;
     57     }
     58     retVal = recv(sHost, buf, sizeof(buf) + 1, 0);
     59     cout << "从服务器接受:" << buf << endl << endl << endl;
     60     while (TRUE)
     61     {
     62         cout << "输入要发给服务器的内容:";
     63         //string msg;
     64         //getline(cin.msg);
     65         char msg[BUFSIZE];
     66         //cin.getline(msg, BUFSIZE);
     67         cin >> msg;
     68         //cout << endl;
     69         ZeroMemory(buf, BUFSIZE);
     70         strcpy(buf, msg);
     71 
     72         retVal = send(sHost, buf, strlen(buf), 0);
     73         if (SOCKET_ERROR == retVal)
     74         {
     75             cout << "发送失败!" << endl;
     76             closesocket(sHost);
     77             WSACleanup();
     78             return -1;
     79         }
     80 
     81         retVal = recv(sHost, buf, sizeof(buf) + 1, 0);
     82         if (SOCKET_ERROR == retVal)
     83         {
     84             cout << "recv()出错!错误代码:#" << WSAGetLastError() << endl;
     85             closesocket(sHost);
     86             WSACleanup();
     87             return -1;
     88         }
     89         cout << "从服务器接受:" << buf << endl << endl;
     90         
     91 
     92         if (strcmp(buf, "quit") == 0)
     93         {
     94             cout << "quit" << endl;
     95             break;
     96         }
     97     }
     98 
     99     closesocket(sHost);
    100     WSACleanup();
    101 
    102     return 0;
    103 
    104 
    105 
    106 }
  • 相关阅读:
    GridView Footer页脚统计实现多行
    Windows cmd 启动 tomcat 中文乱码问题
    git
    CentOS 的 dnf 命令
    不知道是否是wcf 的一个bug
    图像卷积与滤波的一些知识点
    Phaser开源2d引擎 javascript/html5游戏框架
    关于Ldoc
    自写vim插件ldoc.vim,提供智能的lua注释代码补全
    svn diff 使用 vimdiff 作为比较差异工具
  • 原文地址:https://www.cnblogs.com/lyfh/p/4526572.html
Copyright © 2011-2022 走看看