隨筆 - 303  文章 - 883  trackbacks - 0
          <2007年11月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          歡迎光臨! 
          閑聊 QQ:1074961813

          隨筆分類(357)

          我管理的群

          公共blog

          • n維空間
          • Email : java3d@126.com 群 : 12999758

          參與管理的論壇

          好友的blog

          我的其他blog

          朋友的網站

          搜索

          •  

          最新評論

          運行時,請先啟動服務器端

          /*
          * 服務器端
          */


          #include   
          <Winsock2.h>   
          #include   
          <stdio.h>   
          #include   
          <iostream.h> 
          #pragma comment(lib,
          "Ws2_32.lib")  
               
          SOCKET   sockSvc;
          //服務器端socket
          SOCKET   sockConnect;   //連接用的socket
              
          DWORD WINAPI RecvData(LPVOID   lpParameter);  
          //接收線程的函數 
              
          int main()   
          {   
            WORD   wVersionRequested;
          //定義socket1.1或者socket2.0   
            WSADATA   wsaData;   //定義裝載socket版本的變量
            int   err;   //錯誤變量
              
            wVersionRequested 
          = MAKEWORD(2,2);   //定義連接為socket2.0
              
            err  
          =  WSAStartup(wVersionRequested, &wsaData);   //裝載socket2.0支持
            if(0 != err)//判斷是否裝載成功
            {   
              
          return -1;   
            }
             

            
          if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判斷版本號,是否和定義的一樣
            {   
               WSACleanup();   
          //若出問題,卸載支持,并結束程序返回-1
               return -1;     
            }
             
              
            sockSvc 
          = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
            
          /*
            
              SOCKET WSASocket(int af, int type, int protocol,
                           LPWSAPROTOCOL_INFO lpprotocolinfo,
                           GROUP g, DWORD dwflags)

              SOCKET socket(int af, int type, int protocol)
              參數:地址族,套接字類型和協議類型
                    這三個因素共同決定了創建套接字的服務提供者
              
              傳輸服務提供者實現的功能包括建立連接,傳輸數據,實現流控制和差錯控制等函數。
              Ws2_32.dll在應用程序和服務提供者之間實現了媒介的功能

           
            第一
                socket()和WSASocket()函數都能返回一個SOCKET套接字;
                socket()主要實現同步傳輸,Socket庫中例程在應用于阻塞套接口時會阻塞。
                WSASocket()用于異步傳輸,WSASocket()的發送操作和接收操作都可以被重疊使用。
                
                WSASocket()的接收函數可以被多次調用,發出接收緩沖區,準備接收到來的數據。
                           發送函數也可以被多次調用,組成一個發送緩沖區隊列。
                socket()卻只能發過之后等待回消息才可做下一步操作!
            其次    
                WSASocket()所支持的版本如下:   
                                  Version:   Requires   Windows   Sockets2.0.   
                                  Header:   Declared   in   Winsock2.h.   
                socket()所支持老一些的版本,如Windows   Sockets1.0和   
                                  Version:   Requires Windows   Sockets1.1
            
          */

              
            SOCKADDR_IN  addrSvc; 
          //服務器地址信息 
            addrSvc.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //0 接收所有數據包  
            addrSvc.sin_family   =  AF_INET;   
            addrSvc.sin_port  
          =  htons(4000);//監聽 端口
              
            bind(sockSvc,(SOCKADDR
          *)&addrSvc,sizeof(SOCKADDR)); //綁定服務和端口  
              
            listen(sockSvc,
          50);   
            
          /*
              int listen(SOCKET s, int users); 
              服務程序可以調用listen函數使其流套接字s處于監聽狀態。處于監聽狀態的流套接字s將維
              護一個客戶連接請求隊列,該隊列最多容納users個客戶連接請求。假如該函數執行成功,
              則返回0;如果執行失敗,則返回SOCKET_ERROR。
            
          */

              
            SOCKADDR_IN   addrClient;   
            
          int length = sizeof(SOCKADDR);   
              
            
          while(1)   
            
          {   
            sockConnect 
          = accept(sockSvc, (SOCKADDR*)&addrClient,&length); 
            
          /*
             SOCKET accept( 
                SOCKET s, 
                struct sockaddr FAR *addr, 
                int FAR *addrlen 
             ); 
             服務程序調用accept函數從處于監聽狀態的流套接字s的客戶連接請求隊列中取出排在最前的一個客戶請求,
             并且創建一個新的套接字來與客戶套接字創建連接通道,如果連接成功,就返回新創建的套接字的描述符,
             以后與客戶套接字交換數據的是新創建的套接字;如果失敗就返回 INVALID_SOCKET。該函數的第一個參數
             指定處于監聽狀態的流套接字;操作系統利用第二個參數來返回新創建的套接字的地址結構;操作系統利用
             第三個參數來返回新創建的套接字的地址結構的長度。
            
          */

            
          if(INVALID_SOCKET != sockConnect)   
            
          {   
                HANDLE   hThread;   
                hThread
          =CreateThread(NULL,0,RecvData,(LPVOID)sockConnect,0,NULL); 
                
          /*
                /*
                我們得定義一個句柄用來存放它的返回值。還定義一個指向線程ID的DWORD值dwThreadId。
                  CreateThread函數有六個參數分別是
                   LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes
                   DWORD dwStackSize,                         // initial thread stack size
                   LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread function
                   LPVOID lpParameter,                        //argument for new thread
                   DWORD dwCreationFlags,                     // creation flags
                   LPDWORD lpThreadId                         // pointer to receive thread ID
                中第一個參數我們設置為NULL,使這個句柄不能被繼承;第二個參數設置為0,使用默認的堆棧
                大小;第三個參數為線程函數的起始地址,也就是線程函數的函數名;第四個參數要傳遞給線程
                函數的值;第五個參數為0,創建好之后馬上讓線程運行;第六個參數設置為指向線程ID的地址。
                嚴格來說這里需要加錯誤檢測if(NULL == hThead){}
                
          */

                CloseHandle(hThread);   
            }
             
            }
             
              
            Sleep(INFINITE);   
            closesocket(sockConnect);   
            WSACleanup();  
          // 嚴格來說這里需要加錯誤檢測if(0 != WSACleanup()){}
            }
             
              
            DWORD   WINAPI   RecvData(LPVOID   lpParameter)  
          //線程接收函數  
            {   
            SOCKET   socket   
          =   (unsigned  int)lpParameter;   
            
          char   recvBuffer[1024];   
            
          for(;;)   
            
          {   
            
          //receive   data   from   client   
            if(SOCKET_ERROR == recv(socket, recvBuffer, 10240)) //和客戶端的send相對應  
            {   
               cout
          <<"The   receive   data   defeat   or   was   the   client   side   already   withdraws\n"<<endl;   
               
          break;   
            }
             
            cout
          <<"Client says: "<<recvBuffer<<endl;   
            }
             
            closesocket(socket);   
          // 嚴格來說這里需要加錯誤檢測if(0 != closesocket(socket)){}
            return  0;   
          }
             

          /*
          * 客戶端
          */


          #include
          <Winsock2.h>   
          #include
          <stdio.h>   
          #pragma comment(lib,
          "Ws2_32.lib")

          void main()   
          {   
            WORD   wVersionRequested;   
            WSADATA   wsaData;   
            
          int   err;   
              
            wVersionRequested 
          = MAKEWORD(22);   
              
            err 
          = WSAStartup(wVersionRequested, &wsaData);   
            
          if(err != 0){   
               
          return;   
            }
             
              
              
            
          if(LOBYTE(wsaData.wVersion) != 2 ||
               HIBYTE(wsaData.wVersion) 
          != 2 ){   
               
                WSACleanup();   
                
          return;     
            }
             

            SOCKET sockClient 
          = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
            SOCKADDR_IN   addrClient;   
          //服務器地址信息
            addrClient.sin_addr.S_un.S_addr = inet_addr("192.168.94.37");   //要連接的服務地址
            addrClient.sin_family = AF_INET; //協議族  
            addrClient.sin_port = htons(4000);  //請求的端口 
              
            
          char  sendBuffer[1024];   //每次發送的最大數據量
            connect(sockClient, (SOCKADDR*)&addrClient, sizeof(SOCKADDR));//連接服務器端   
            while(true)   
            
          {   
              
          /*send   data   to   service*/   
              printf(
          "Please   input   data:\n");   
              
          if(gets(sendBuffer) == NULL)  //輸入要發送的數據 
              break;   
              
          else   
              
          {   
                
          if(SOCKET_ERROR == send(sockClient,sendBuffer,
                    strlen(sendBuffer)
          +1,0)) //TCP方式發送  
                {   
                   printf(
          "Transmission data defeat!\n");   
                   
          break;   
                }
             
              }
             
            }
             
            closesocket(sockClient);    
          // 嚴格來說這里需要加錯誤檢測if(0 != closesocket(socket)){}
            WSACleanup();   
          }


          地震讓大伙知道:居安思危,才是生存之道。
          posted on 2007-11-27 23:44 小尋 閱讀(7228) 評論(3)  編輯  收藏 所屬分類: c/c++/C#/pasic/vb/php/asp(.net)/win-cgi/xml...

          FeedBack:
          # re: windows網絡編程【003】實現簡單WSASocket的C/S結構-_-!~~~~~~ [未登錄] 2008-07-31 14:56 小白
          客戶端能指定自己的連接端口嗎?怎么指定?  回復  更多評論
            
          # re: windows網絡編程【003】實現簡單WSASocket的C/S結構-_-!~~~~~~ [未登錄] 2008-07-31 17:04 小白
          我找到了指定客戶端端口號的方法,是使用bind函數。但我又碰到另一個問題:綁定了一個端口號后,怎么釋放這個端口號,以供下一次再使用這個端口號。  回復  更多評論
            
          # re: windows網絡編程【003】實現簡單WSASocket的C/S結構-_-!~~~~~~ [未登錄] 2014-07-17 15:22 fedora
          博主在細節上講得很清楚,編程很規范,受教了!  回復  更多評論
            
          主站蜘蛛池模板: 腾冲县| 南开区| 绥江县| 江都市| 乾安县| 高雄市| 共和县| 汝州市| 政和县| 三穗县| 大名县| 行唐县| 雅江县| 琼结县| 泰和县| 丽水市| 定州市| 揭东县| 乌苏市| 彭泽县| 泾川县| 鹰潭市| 湟中县| 平遥县| 石城县| 汕尾市| 山阳县| 明水县| 团风县| 巧家县| 会宁县| 栾川县| 班戈县| 龙陵县| 威信县| 安陆市| 井冈山市| 玉山县| 济宁市| 盖州市| 基隆市|