windows下socket学习(一)

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

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

windows下socket学习(一)_第1张图片

我晕,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 << "\t" << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":"
118         << ((LPClientStruct)param)->csSockAddr_In.sin_port << "\t接入服务器" << 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 << "\t被强制断开连接!" << 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 << "\t说:" << 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 }

 

你可能感兴趣的:(windows)