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 }
  • 相关阅读:
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 3037 Saving Beans【Lucas定理】【模板题】【模板】【组合数取余】
    8.Math 对象
  • 原文地址:https://www.cnblogs.com/lyfh/p/4526572.html
Copyright © 2011-2022 走看看