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

          歡迎光臨! 
          閑聊 QQ:1074961813

          隨筆分類(357)

          我管理的群

          公共blog

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

          參與管理的論壇

          好友的blog

          我的其他blog

          朋友的網(wǎng)站

          搜索

          •  

          最新評(píng)論

          運(yùn)行時(shí),請(qǐng)先啟動(dòng)服務(wù)器端

          /*
          * 服務(wù)器端
          */


          #include   
          <Winsock2.h>   
          #include   
          <stdio.h>   
          #include   
          <iostream.h> 
          #pragma comment(lib,
          "Ws2_32.lib")  
               
          SOCKET   sockSvc;
          //服務(wù)器端socket
          SOCKET   sockConnect;   //連接用的socket
              
          DWORD WINAPI RecvData(LPVOID   lpParameter);  
          //接收線程的函數(shù) 
              
          int main()   
          {   
            WORD   wVersionRequested;
          //定義socket1.1或者socket2.0   
            WSADATA   wsaData;   //定義裝載socket版本的變量
            int   err;   //錯(cuò)誤變量
              
            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)//判斷版本號(hào),是否和定義的一樣
            {   
               WSACleanup();   
          //若出問(wèn)題,卸載支持,并結(jié)束程序返回-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)
              參數(shù):地址族,套接字類型和協(xié)議類型
                    這三個(gè)因素共同決定了創(chuàng)建套接字的服務(wù)提供者
              
              傳輸服務(wù)提供者實(shí)現(xiàn)的功能包括建立連接,傳輸數(shù)據(jù),實(shí)現(xiàn)流控制和差錯(cuò)控制等函數(shù)。
              Ws2_32.dll在應(yīng)用程序和服務(wù)提供者之間實(shí)現(xiàn)了媒介的功能

           
            第一
                socket()和WSASocket()函數(shù)都能返回一個(gè)SOCKET套接字;
                socket()主要實(shí)現(xiàn)同步傳輸,Socket庫(kù)中例程在應(yīng)用于阻塞套接口時(shí)會(huì)阻塞。
                WSASocket()用于異步傳輸,WSASocket()的發(fā)送操作和接收操作都可以被重疊使用。
                
                WSASocket()的接收函數(shù)可以被多次調(diào)用,發(fā)出接收緩沖區(qū),準(zhǔn)備接收到來(lái)的數(shù)據(jù)。
                           發(fā)送函數(shù)也可以被多次調(diào)用,組成一個(gè)發(fā)送緩沖區(qū)隊(duì)列。
                socket()卻只能發(fā)過(guò)之后等待回消息才可做下一步操作!
            其次    
                WSASocket()所支持的版本如下:   
                                  Version:   Requires   Windows   Sockets2.0.   
                                  Header:   Declared   in   Winsock2.h.   
                socket()所支持老一些的版本,如Windows   Sockets1.0和   
                                  Version:   Requires Windows   Sockets1.1
            
          */

              
            SOCKADDR_IN  addrSvc; 
          //服務(wù)器地址信息 
            addrSvc.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //0 接收所有數(shù)據(jù)包  
            addrSvc.sin_family   =  AF_INET;   
            addrSvc.sin_port  
          =  htons(4000);//監(jiān)聽(tīng) 端口
              
            bind(sockSvc,(SOCKADDR
          *)&addrSvc,sizeof(SOCKADDR)); //綁定服務(wù)和端口  
              
            listen(sockSvc,
          50);   
            
          /*
              int listen(SOCKET s, int users); 
              服務(wù)程序可以調(diào)用listen函數(shù)使其流套接字s處于監(jiān)聽(tīng)狀態(tài)。處于監(jiān)聽(tīng)狀態(tài)的流套接字s將維
              護(hù)一個(gè)客戶連接請(qǐng)求隊(duì)列,該隊(duì)列最多容納users個(gè)客戶連接請(qǐng)求。假如該函數(shù)執(zhí)行成功,
              則返回0;如果執(zhí)行失敗,則返回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 
             ); 
             服務(wù)程序調(diào)用accept函數(shù)從處于監(jiān)聽(tīng)狀態(tài)的流套接字s的客戶連接請(qǐng)求隊(duì)列中取出排在最前的一個(gè)客戶請(qǐng)求,
             并且創(chuàng)建一個(gè)新的套接字來(lái)與客戶套接字創(chuàng)建連接通道,如果連接成功,就返回新創(chuàng)建的套接字的描述符,
             以后與客戶套接字交換數(shù)據(jù)的是新創(chuàng)建的套接字;如果失敗就返回 INVALID_SOCKET。該函數(shù)的第一個(gè)參數(shù)
             指定處于監(jiān)聽(tīng)狀態(tài)的流套接字;操作系統(tǒng)利用第二個(gè)參數(shù)來(lái)返回新創(chuàng)建的套接字的地址結(jié)構(gòu);操作系統(tǒng)利用
             第三個(gè)參數(shù)來(lái)返回新創(chuàng)建的套接字的地址結(jié)構(gòu)的長(zhǎng)度。
            
          */

            
          if(INVALID_SOCKET != sockConnect)   
            
          {   
                HANDLE   hThread;   
                hThread
          =CreateThread(NULL,0,RecvData,(LPVOID)sockConnect,0,NULL); 
                
          /*
                /*
                我們得定義一個(gè)句柄用來(lái)存放它的返回值。還定義一個(gè)指向線程ID的DWORD值dwThreadId。
                  CreateThread函數(shù)有六個(gè)參數(shù)分別是
                   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
                中第一個(gè)參數(shù)我們?cè)O(shè)置為NULL,使這個(gè)句柄不能被繼承;第二個(gè)參數(shù)設(shè)置為0,使用默認(rèn)的堆棧
                大小;第三個(gè)參數(shù)為線程函數(shù)的起始地址,也就是線程函數(shù)的函數(shù)名;第四個(gè)參數(shù)要傳遞給線程
                函數(shù)的值;第五個(gè)參數(shù)為0,創(chuàng)建好之后馬上讓線程運(yùn)行;第六個(gè)參數(shù)設(shè)置為指向線程ID的地址。
                嚴(yán)格來(lái)說(shuō)這里需要加錯(cuò)誤檢測(cè)if(NULL == hThead){}
                
          */

                CloseHandle(hThread);   
            }
             
            }
             
              
            Sleep(INFINITE);   
            closesocket(sockConnect);   
            WSACleanup();  
          // 嚴(yán)格來(lái)說(shuō)這里需要加錯(cuò)誤檢測(cè)if(0 != WSACleanup()){}
            }
             
              
            DWORD   WINAPI   RecvData(LPVOID   lpParameter)  
          //線程接收函數(shù)  
            {   
            SOCKET   socket   
          =   (unsigned  int)lpParameter;   
            
          char   recvBuffer[1024];   
            
          for(;;)   
            
          {   
            
          //receive   data   from   client   
            if(SOCKET_ERROR == recv(socket, recvBuffer, 10240)) //和客戶端的send相對(duì)應(yīng)  
            {   
               cout
          <<"The   receive   data   defeat   or   was   the   client   side   already   withdraws\n"<<endl;   
               
          break;   
            }
             
            cout
          <<"Client says: "<<recvBuffer<<endl;   
            }
             
            closesocket(socket);   
          // 嚴(yán)格來(lái)說(shuō)這里需要加錯(cuò)誤檢測(cè)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;   
          //服務(wù)器地址信息
            addrClient.sin_addr.S_un.S_addr = inet_addr("192.168.94.37");   //要連接的服務(wù)地址
            addrClient.sin_family = AF_INET; //協(xié)議族  
            addrClient.sin_port = htons(4000);  //請(qǐng)求的端口 
              
            
          char  sendBuffer[1024];   //每次發(fā)送的最大數(shù)據(jù)量
            connect(sockClient, (SOCKADDR*)&addrClient, sizeof(SOCKADDR));//連接服務(wù)器端   
            while(true)   
            
          {   
              
          /*send   data   to   service*/   
              printf(
          "Please   input   data:\n");   
              
          if(gets(sendBuffer) == NULL)  //輸入要發(fā)送的數(shù)據(jù) 
              break;   
              
          else   
              
          {   
                
          if(SOCKET_ERROR == send(sockClient,sendBuffer,
                    strlen(sendBuffer)
          +1,0)) //TCP方式發(fā)送  
                {   
                   printf(
          "Transmission data defeat!\n");   
                   
          break;   
                }
             
              }
             
            }
             
            closesocket(sockClient);    
          // 嚴(yán)格來(lái)說(shuō)這里需要加錯(cuò)誤檢測(cè)if(0 != closesocket(socket)){}
            WSACleanup();   
          }


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

          FeedBack:
          # re: windows網(wǎng)絡(luò)編程【003】實(shí)現(xiàn)簡(jiǎn)單WSASocket的C/S結(jié)構(gòu)-_-!~~~~~~ [未登錄](méi) 2008-07-31 14:56 小白
          客戶端能指定自己的連接端口嗎?怎么指定?  回復(fù)  更多評(píng)論
            
          # re: windows網(wǎng)絡(luò)編程【003】實(shí)現(xiàn)簡(jiǎn)單WSASocket的C/S結(jié)構(gòu)-_-!~~~~~~ [未登錄](méi) 2008-07-31 17:04 小白
          我找到了指定客戶端端口號(hào)的方法,是使用bind函數(shù)。但我又碰到另一個(gè)問(wèn)題:綁定了一個(gè)端口號(hào)后,怎么釋放這個(gè)端口號(hào),以供下一次再使用這個(gè)端口號(hào)。  回復(fù)  更多評(píng)論
            
          # re: windows網(wǎng)絡(luò)編程【003】實(shí)現(xiàn)簡(jiǎn)單WSASocket的C/S結(jié)構(gòu)-_-!~~~~~~ [未登錄](méi) 2014-07-17 15:22 fedora
          博主在細(xì)節(jié)上講得很清楚,編程很規(guī)范,受教了!  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 灵山县| 苏尼特右旗| 宝山区| 邵阳市| 托里县| 富裕县| 连江县| 丰原市| 湄潭县| 德州市| 右玉县| 天水市| 勐海县| 射洪县| 岳阳县| 饶河县| 沙田区| 蕲春县| 屏东县| 武宁县| 腾冲县| 原平市| 泰州市| 隆安县| 米泉市| 鸡东县| 六安市| 凤冈县| 靖边县| 额敏县| 东乡族自治县| 长岛县| 龙泉市| 南靖县| 浙江省| 鄂温| 珠海市| 霞浦县| 叶城县| 清新县| 江源县|