程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> windows下socket學習(一),windows下socket學習

windows下socket學習(一),windows下socket學習

編輯:C++入門知識

windows下socket學習(一),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 << "\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 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved