久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

如何在Windows環(huán)境下的VS中安裝使用Google Protobuf完成SOCKET通信

 9loong 2012-08-07
http://blog.csdn.net/monkey_d_meng/article/details/5894910

如何在Windows環(huán)境下的VS中安裝使用Google Protobuf完成SOCKET通信

 

最近一段時間,,由于項目的需要,接觸到了Protobuf這個東東,,在Linux環(huán)境下,,體驗了一把,感覺挺不錯,,很方便,,且高效。是一個非常值得學習掌握和應用的數(shù)據(jù)抽象,、平臺無關(guān),、功能強大、(此處省略1000字)的開源工具,。

Google雖然把Protobuf做成了跨平臺,、跨語言,但作為微軟的死對頭,,它在readme.txt文件的第一句話就表明了態(tài)度:為了考慮部分MSVC的用戶,,Protobuf提供了針對VS的安裝說明,但Protobuf最好用于Unix環(huán)境下,。

在上一篇博客中,,我介紹了如何在Linux環(huán)境下安裝Protobuf,現(xiàn)在讓我們了解一下Windows環(huán)境下,,如何在VS中使用Protobuf,,注意是VS,在VC6的環(huán)境下,,我搞弄了一個晚上都沒成功,,所以推薦VS2005或者以上版本:

 

1.下載protobuff,我下的是2.3.0版本

最新的protobuf可以到Google Code上下載:http://code.google.com/p/protobuf/downloads/list

當前版本為2.3.0,,下載兩個壓縮包:protoc-2.3.0-win32.zipprotobuf-2.3.0.zip,,前者是protobuf的編譯器,后者包含了有三程序語言的開發(fā)包,。

 

2.解壓

首先解壓protoc-2.3.0-win32.zip,,把protoc.exe文件放到path路徑中,最簡單的做法就是把這個文件拷貝到C:/WINDOWS目錄下,。

解壓protobuf-2.3.0.zip文件,,將文件加壓到C盤根目錄,,主文件位于C:/protobuf-2.3.0/protobuf-2.3.0目錄下。

 

3.安裝操作

1使用VS2005編譯proto,,VS工程目錄位于vsprojects目錄中,,工程名字為protobuf.sln

 

2)選擇“生成”à“生成解決方案”選項進行編譯,,編譯過程中可能會由于編譯的順序報錯誤,,可以使用手工逐個順序編譯生成,可能會比較順利,。按照下圖的順序,,右鍵“重新生成”,逐個編譯,。但是我在實習操作過程中,,libprotobuf-lite工程重來都沒有成功編譯通過過。淡定先,,這個不會影響大局的,。

 


3)編譯完成會在目錄vsprojects下的Debug目錄中生成libexe文件。

生成清單如下:

exe文件:

2010-04-15  09:51         950,272 lite-test.exe

2010-04-15  09:50         3,219,456 protoc.exe

2010-04-15  09:48         9,228,288 tests.exe

2010-04-15  09:56         2,519,040 test_plugin.exe

 

lib文件:

2010-04-15  09:50        2,685,922 libprotobuf-lite.lib

2010-04-15  09:56        24,100,794 libprotobuf.lib

2010-04-15  09:56        17,302,068 libprotoc.lib

其實我在測試過程中,,lite-test.exelibprotobuf-lite.lib并沒有生成,,因為編譯錯誤了,但這并不影響大局,,淡定先,。

 

4OK,至此,,我們已經(jīng)完成了編譯工作,,下面需要進行的是protobuf的測試。我們需要使用到之前VS編譯出來的libprotobuf.liblibprotoc.lib完成一個C/S結(jié)構(gòu)的SOCKET通信測試,。

 

àProtobuf的測試

VS2005下,,創(chuàng)建兩個新的工程,分別命名為serverclient,,每個工程都需要引用protobuf的頭文件和lib文件,。

一、添加protobuf頭文件操作:右擊項目à屬性à配置屬性àC/C++à常規(guī) (也命令行可在中添加),。具體路徑:C:/protobuf-2.3.0/protobuf-2.3.0/src

二,、添加protobuflib文件操作:右擊項目à屬性à配置屬性à鏈接器à常規(guī)(也可在命令行中添加)。具體路徑:C:/protobuf-2.3.0/protobuf-2.3.0/vsprojects/Debug

三,、CMD窗口下編譯生成頭文件:

C:/protobuf-2.3.0/protobuf-2.3.0/examples>protoc -I=./ --cpp_out=./ people.proto

proto文件生成的文件放到當前目錄。

我們得到了兩個文件生:people.pb.hpeople.pb.cc

 

people.proto文件內(nèi)容如下:

  1. package CPFS;     
  2. message People  
  3. {     
  4.   required string name = 1;     
  5.   required int32 id = 2;     
  6.   required string email = 3;     
  7. }  
 

 

四,、serverclient端源代碼:

server端源代碼:

  1. #include "common/op_socket.h"  
  2. #include "people.pb.h"  
  3. #pragma comment(lib, "libprotobuf.lib")  
  4. #pragma comment(lib, "libprotoc.lib")  
  5. using namespace std;  
  6. int main()     
  7. {     
  8.     GOOGLE_PROTOBUF_VERIFY_VERSION;  
  9.     OP_SOCKET server_sockfd;  
  10.     OP_SOCKET new_server_sockfd;  
  11.     OP_SOCKADDR_IN server_addr;  
  12.     OP_SOCKADDR_IN client_addr;  
  13.     OP_SOCKLEN_T sin_size;  
  14.     char buffer[BUFFER_SIZE + 1];  
  15.     int bytes;  
  16.     string str;  
  17.     string data;  
  18.     CPFS::People p;  
  19. #ifdef WIN32  
  20.     WSADATA  Ws;  
  21.     //Init Windows Socket  
  22.     if (WSAStartup(MAKEWORD(2,2), &Ws) != 0)  
  23.     {  
  24.         fprintf(stderr, "Init Windows Socket Failed::%s", GetLastError());  
  25.         return EXIT_FAILURE;  
  26.     }  
  27. #endif  
  28.     server_sockfd = op_socket(AF_INET, SOCK_STREAM, 0);   
  29.     op_set_sockaddr_in(server_addr, AF_INET, htons(INADDR_ANY), htons(OP_PORT));  
  30.     op_bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));     
  31.     op_listen(server_sockfd, LISTEN_QUEUE);     
  32.     
  33.     while(1)  
  34.     {     
  35.         sin_size = sizeof(struct sockaddr_in);  
  36.         new_server_sockfd = op_accept(server_sockfd, (struct sockaddr *)&client_addr, &sin_size);  
  37.     
  38.         bytes = op_recv(new_server_sockfd, buffer, BUFFER_SIZE, 0);  
  39.         buffer[bytes] = '/0';  
  40.         str = buffer;  
  41.         cout << "You got a message from " << inet_ntoa(client_addr.sin_addr) << endl;  
  42.         cout << "client_addr Message: " << str << endl;  
  43.         if(str == "get")  
  44.         {  
  45.             p.set_id(1);  
  46.                 p.set_name("monkey");  
  47.                 p.set_email("[email protected]");  
  48.                 p.SerializeToString(&data);  
  49.             char dst[BUFFER_SIZE];  
  50.             strcpy(dst, data.c_str());  
  51.                 op_send(new_server_sockfd, dst, sizeof(dst), 0);  
  52.         }  
  53.         else  
  54.         {  
  55.             op_send(new_server_sockfd, "Fucking client_addr!/n", 16, 0);  
  56.         }  
  57.         op_close(new_server_sockfd);  
  58.     }     
  59.     op_close(server_sockfd);  
  60.     google::protobuf::ShutdownProtobufLibrary();  
  61.     getchar();  
  62. #ifdef WIN32  
  63.     WSACleanup();  
  64. #endif  
  65.     return EXIT_SUCCESS;  
  66. }  

client源代碼:

 

  1. #include "common/op_socket.h"  
  2. #include "people.pb.h"  
  3. #pragma comment(lib, "libprotobuf.lib")  
  4. #pragma comment(lib, "libprotoc.lib")  
  5. using namespace std;  
  6. int main(int argc, char **argv)     
  7. {  
  8.     GOOGLE_PROTOBUF_VERIFY_VERSION;  
  9.     OP_SOCKET client_sockfd;  
  10.     OP_SOCKADDR_IN server_addr;  
  11.     OP_SOCKADDR_IN client_addr;  
  12.     char buffer[BUFFER_SIZE + 1];  
  13.     int bytes;  
  14.     CPFS::People p;  
  15.     if (argc != 2)  
  16.     {  
  17.         printf("Usage: %s /"COMMAND/"/n",argv[0]);  
  18.         exit(0);  
  19.     }  
  20. #ifdef WIN32  
  21.     WSADATA  Ws;  
  22.     //Init Windows Socket  
  23.     if (WSAStartup(MAKEWORD(2,2), &Ws) != 0)  
  24.     {  
  25.         fprintf(stderr, "Init Windows Socket Failed::%s", GetLastError());  
  26.         return EXIT_FAILURE;  
  27.     }  
  28. #endif  
  29.     client_sockfd = op_socket(AF_INET, SOCK_STREAM, 0);  
  30.     op_set_sockaddr_in(server_addr, AF_INET, op_inet_addr(DEFAULT_SERVER_IP), htons(OP_PORT));  
  31.     op_connect(client_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));  
  32.     op_send(client_sockfd, argv[1], 20, 0);  
  33.     bytes = op_recv(client_sockfd, buffer, BUFFER_SIZE, 0);  
  34.     buffer[bytes] = '/0';  
  35.     string data = buffer;  
  36.     p.ParseFromString(data);  
  37.     cout << "Name: " << p.name() << endl;  
  38.     cout << "ID: " << p.id() << endl;  
  39.     cout << "Email: " << p.email() << endl;  
  40.     op_close(client_sockfd);  
  41. #ifdef WIN32  
  42.     WSACleanup();  
  43. #endif  
  44.     google::protobuf::ShutdownProtobufLibrary();  
  45.     return EXIT_SUCCESS;  
  46. }  

五,、因為上述兩個代碼用到了我寫了一個初級版本的SOCKET跨平臺的庫,,這里貼出來,很齪,,但還可以用,,小弟也才開始寫socket程序。這個庫文件要放到common/目錄下面,。

op_socket.h源代碼:

 

  1. #ifndef OP_SOCKET_H_  
  2. #define OP_SOCKET_H_  
  3. #include <stdio.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <stdlib.h>  
  7. #include <iostream>  
  8. #include <string>  
  9. #ifndef WIN32  
  10.     #include <sys/types.h>  
  11.     #include <sys/wait.h>  
  12.     #include <sys/socket.h>  
  13.     #include <arpa/inet.h>  
  14.     #include <netinet/in.h>  
  15.     #include <signal.h>  
  16.     #include <netdb.h>  
  17.     #include <unistd.h>  
  18.     #include <fcntl.h>  
  19. #else  
  20.     #include <winsock2.h>  
  21.     #pragma comment(lib, "ws2_32.lib")  
  22. #endif  
  23. // Linux  
  24. #ifndef WIN32  
  25.     #define OP_SOCKET               int  
  26.     #define OP_SOCKADDR_IN          struct sockaddr_in  
  27.     #define OP_SOCKADDR             struct sockaddr  
  28.     #define OP_SOCKLEN_T            socklen_t  
  29. // Windows  
  30. #else  
  31.     #define OP_SOCKET               SOCKET  
  32.     #define OP_SOCKADDR_IN          SOCKADDR_IN  
  33.     #define OP_SOCKADDR             SOCKADDR  
  34.     #define OP_SOCKLEN_T            int FAR  
  35. #endif  
  36. #define OP_PORT                     8888  
  37. #define BUFFER_SIZE                 1024  
  38. #define LISTEN_QUEUE                20  
  39. #define MD5_SIZE                    32  
  40. #define FILE_PATH_MAX_SIZE          512  
  41. #define FILE_NAME_MAX_SIZE          260  
  42. #define FILE_FULL_NAME_MAX_SIZE     1024  
  43. #define HOST                        "localhost"  
  44. #define DEFAULT_SERVER_IP           "127.0.0.1"  
  45. #ifndef WIN32  
  46.     #define CLI_FILE_PATH           "/tmp/data/client/" // 客戶端存儲文件的初始化路徑  
  47.     #define SERV_FILE_PATH          "/tmp/data/server/" // 服務器端存儲文件的初始化路徑  
  48. #else  
  49.     #define CLI_FILE_PATH           "D://download//"    // 客戶端存儲文件的初始化路徑  
  50.     #define SERV_FILE_PATH          "D://data//"        // 客戶端存儲文件的初始化路徑  
  51. #endif  
  52. // 把一段內(nèi)存區(qū)的內(nèi)容全部設置為  
  53. void op_clean_buffer(void *buffer, int len);  
  54. // 設置sockaddr_in, internet協(xié)議族, INADDR_ANY表示自動獲取本機地址  
  55. void op_set_sockaddr_in(OP_SOCKADDR_IN &addr, short op_sin_family, unsigned long op_s_addr, unsigned short op_sin_port);  
  56. // 創(chuàng)建用于internet的流協(xié)議(TCP)socket, 用server_socket代表服務器socket  
  57. int op_socket(int domain, int type, int protocol);  
  58. // 接受一個到server_socket代表的socket的一個連接  
  59. // 如果沒有連接請求,就等待到有連接請求--這是accept函數(shù)的特性  
  60. // accept函數(shù)返回一個新的socket, 這個socket(new_server_socket)用于同連接到的客戶的通信  
  61. // new_server_socket代表了服務器和客戶端之間的一個通信通道  
  62. // accept函數(shù)把連接到的客戶端信息填寫到客戶端的socket地址結(jié)構(gòu)client_addr中  
  63. int op_accept(OP_SOCKET sockfd, OP_SOCKADDR *addr, OP_SOCKLEN_T *addrlen);  
  64. // IP的點分十記轉(zhuǎn)化為IP的結(jié)構(gòu)體  
  65. unsigned long op_inet_addr(const char *dst);  
  66. // 向服務器發(fā)起連接,連接成功后client_socket代表了客戶機和服務器的一個socket連接  
  67. int op_connect(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen);  
  68. // addr指定的地址分配給與文件描述符socket關(guān)聯(lián)的未命名套接字  
  69. int op_bind(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen);  
  70. // 監(jiān)聽client請求,,backlog指定最大連接數(shù)  
  71. int op_listen(OP_SOCKET sockfd, int backlog);  
  72. // send發(fā)送消息  
  73. int op_send(OP_SOCKET sockfd, const char *buffer, size_t len, int flags);  
  74. // recv接收消息  
  75. int op_recv(OP_SOCKET sockfd, char *buffer, size_t len, int flags);  
  76. // 關(guān)閉socket或文件指針  
  77. FILE* op_fopen(const char *path, const char *mode);  
  78. // 打開文件  
  79. int op_close(OP_SOCKET sockfd);  
  80. // 關(guān)閉文件指針  
  81. int op_fclose(FILE *stream);  
  82. // 休眠函數(shù)  
  83. void op_sleep(int micro_seconds);  
  84. // 字符串比較函數(shù)  
  85. int op_stricmp(char *s1,char * s2);  
  86. #endif  

op_socket.cpp源文件代碼:

 

  1. #include "op_socket.h"  
  2. // 把一段內(nèi)存區(qū)的內(nèi)容全部設置為  
  3. void op_clean_buffer(void *buffer, int len)  
  4. {  
  5. #ifndef WIN32  
  6.     bzero(buffer, len);  
  7. #else  
  8.     memset(buffer, 0, len);  
  9. #endif  
  10. }  
  11. // 設置sockaddr_in  
  12. void op_set_sockaddr_in(OP_SOCKADDR_IN &addr, short op_sin_family, unsigned long op_s_addr, unsigned short op_sin_port)  
  13. {  
  14.     op_clean_buffer(&addr, sizeof(addr));  
  15.     addr.sin_family = op_sin_family;  
  16.     addr.sin_addr.s_addr = op_s_addr;  
  17.     addr.sin_port = op_sin_port;  
  18. }  
  19. // 創(chuàng)建socket  
  20. int op_socket(int domain, int type, int protocol)  
  21. {  
  22.     int sockfd;  
  23. #ifndef WIN32  
  24.     if ((sockfd = socket(domain, type, protocol)) < 0)  
  25. #else  
  26.     if ((sockfd = socket(domain, type, protocol)) == INVALID_SOCKET)  
  27. #endif  
  28.     {  
  29.         fprintf(stderr, "op_socket error/n");  
  30.         exit(EXIT_FAILURE);  
  31.     }  
  32.     return sockfd;  
  33. }  
  34. // 接收客戶端的socket請求  
  35. int op_accept(OP_SOCKET sockfd, OP_SOCKADDR *addr, OP_SOCKLEN_T *addrlen)  
  36. {  
  37.     int ret;  
  38.     if ((ret = accept(sockfd, addr, addrlen)) < 0)  
  39.     {  
  40.         fprintf(stderr, "op_accept error/n");  
  41.         exit(EXIT_FAILURE);  
  42.     }  
  43.     return ret;  
  44. }  
  45. // IP的點分十記轉(zhuǎn)化為IP的結(jié)構(gòu)體  
  46. unsigned long op_inet_addr(const char *dst)  
  47. {  
  48.     long ret;  
  49.     if ((ret = inet_addr(dst)) < 0)  
  50.     {  
  51.         fprintf(stderr, "op_inet_addr error for %s/n", dst);  
  52.         exit(EXIT_FAILURE);  
  53.     }  
  54.     return (unsigned long)ret;  
  55. }  
  56. // sockfd指定的套接字連接到addr指定的服務器套接字  
  57. int op_connect(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen)  
  58. {  
  59.     int ret;  
  60.     if ((ret = connect(sockfd, addr, addrlen)) < 0)  
  61.     {  
  62.         fprintf(stderr, "op_connect error/n");  
  63.         exit(EXIT_FAILURE);  
  64.     }  
  65.     return ret;  
  66. }  
  67. // addr指定的地址分配給與文件描述符socket關(guān)聯(lián)的未命名套接字  
  68. int op_bind(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen)  
  69. {  
  70.     int ret;  
  71.     if ((ret = bind(sockfd, addr, addrlen)) < 0)  
  72.     {  
  73.         fprintf(stderr, "op_bind error/n");  
  74.         exit(EXIT_FAILURE);  
  75.     }  
  76.     return ret;  
  77. }  
  78. // 監(jiān)聽client請求,backlog指定最大連接數(shù)  
  79. int op_listen(OP_SOCKET sockfd, int backlog)  
  80. {  
  81.     int ret;  
  82.     if ((ret = listen(sockfd, backlog)) < 0)  
  83.     {  
  84.         fprintf(stderr, "op_listen error/n");  
  85.         exit(EXIT_FAILURE);  
  86.     }  
  87.     return ret;  
  88. }  
  89. // send發(fā)送消息  
  90. int op_send(OP_SOCKET sockfd, const char *buffer, size_t len, int flags)  
  91. {  
  92.     int ret;  
  93.     if ((ret = send(sockfd, buffer, len, flags)) < 0)  
  94.     {  
  95.         fprintf(stderr, "op_send error/n");  
  96.         exit(EXIT_FAILURE);  
  97.     }  
  98.     return ret;  
  99. }  
  100. // recv接收消息  
  101. int op_recv(OP_SOCKET sockfd, char *buffer, size_t len, int flags)  
  102. {  
  103.     size_t ret;  
  104.     op_clean_buffer(buffer, len);  
  105.     if ((ret = recv(sockfd, buffer, len, flags)) < 0)  
  106.     {  
  107.         fprintf(stderr, "op_recv error/n");  
  108.         exit(EXIT_FAILURE);  
  109.     }  
  110.     return ret;  
  111. }  
  112. // 關(guān)閉socket或文件指針  
  113. int op_close(OP_SOCKET sockfd)  
  114. {  
  115.     int ret;  
  116. #ifndef WIN32  
  117.     if ((ret = close(sockfd)) < 0)  
  118. #else  
  119.     if((ret = closesocket(sockfd)) < 0)  
  120. #endif  
  121.     {  
  122.         fprintf(stderr, "op_close error/n");  
  123.         exit(EXIT_FAILURE);  
  124.     }  
  125.     return ret;  
  126. }  
  127. // 打開文件  
  128. FILE* op_fopen(const char *path, const char *mode)  
  129. {  
  130.     FILE *fp = fopen(path, mode);  
  131.     if (NULL == fp)  
  132.     {  
  133.         printf("File:/t%s Can Not Open To Write/n", path);  
  134.         exit(EXIT_FAILURE);  
  135.     }  
  136.     return fp;  
  137. }  
  138. // 關(guān)閉文件指針  
  139. int op_fclose(FILE *stream)  
  140. {  
  141.     int ret;  
  142.     if ((ret = fclose(stream)) < 0)  
  143.     {  
  144.         fprintf(stderr, "op_fclose error/n");  
  145.         exit(EXIT_FAILURE);  
  146.     }  
  147.     return ret;  
  148. }  
  149. // 休眠函數(shù),,對于usleep為微秒級別,,對于Sleep為毫秒級別  
  150. void op_sleep(int micro_seconds)  
  151. {  
  152. #ifndef WIN32  
  153.     usleep(micro_seconds);  
  154. #else  
  155.     Sleep(micro_seconds);  
  156. #endif  
  157. }  
  158. // 字符串比較函數(shù)  
  159. int op_stricmp(char *s1,char * s2)  
  160. {  
  161. #ifndef WIN32  
  162.     return strcasecmp(s1, s2);  
  163. #else  
  164.     return stricmp(s1, s2);  
  165. #endif  
  166. }  

六、完成了上述的操作之后,,就可以分別對clientserver端進行編譯了,,先啟動server端服務器,然后用命令行的形式運行client端,,就可以成功了吧,。哈哈!我們來看一下使用protobuf進行socket通信的實際效果,!給大家截個圖,!

 

 

 

最近項目緊,沒空時間來好好寫博客,,只能粗略記錄一下,,等實習結(jié)束后,要把這段時間的所學所感好好總結(jié)下來,。

順便說一下,,op_socket這個SOCKET是跨平臺的,寫個makefile可以直接在UNIX環(huán)境下運行的,,咳咳,,寫的太齪了大家見笑了。,。,。



(###)

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多