码:
[cpp]
view plain
copy
- #include "common/op_socket.h"
- #include "people.pb.h"
- #pragma comment(lib, "libprotobuf.lib")
- #pragma comment(lib, "libprotoc.lib")
- using namespace std;
- int main(int argc, char **argv)
- {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
- OP_SOCKET client_sockfd;
- OP_SOCKADDR_IN server_addr;
- OP_SOCKADDR_IN client_addr;
- char buffer[BUFFER_SIZE + 1];
- int bytes;
- CPFS::People p;
- if (argc != 2)
- {
- printf("Usage: %s /"COMMAND/"/n",argv[0]);
- exit(0);
- }
- #ifdef WIN32
- WSADATA Ws;
- //Init Windows Socket
- if (WSAStartup(MAKEWORD(2,2), &Ws) != 0)
- {
- fprintf(stderr, "Init Windows Socket Failed::%s", GetLastError());
- return EXIT_FAILURE;
- }
- #endif
- client_sockfd = op_socket(AF_INET, SOCK_STREAM, 0);
- op_set_sockaddr_in(server_addr, AF_INET, op_inet_addr(DEFAULT_SERVER_IP), htons(OP_PORT));
- op_connect(client_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
- op_send(client_sockfd, argv[1], 20, 0);
- bytes = op_recv(client_sockfd, buffer, BUFFER_SIZE, 0);
- buffer[bytes] = '/0';
- string data = buffer;
- p.ParseFromString(data);
- cout << "Name: " << p.name() << endl;
- cout << "ID: " << p.id() << endl;
- cout << "Email: " << p.email() << endl;
- op_close(client_sockfd);
- #ifdef WIN32
- WSACleanup();
- #endif
- google::protobuf::ShutdownProtobufLibrary();
- return EXIT_SUCCESS;
- }
五、因为上述两个代码用到了我写了一个初级版本的SOCKET跨平台的库,这里贴出来,很龊,但还可以用,小弟也才开始写socket程序。这个库文件要放到common/目录下面。
op_socket.h源代码:
[cpp]
view plain
copy
- #ifndef OP_SOCKET_H_
- #define OP_SOCKET_H_
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- #include <iostream>
- #include <string>
- #ifndef WIN32
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <signal.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <fcntl.h>
- #else
- #include <winsock2.h>
- #pragma comment(lib, "ws2_32.lib")
- #endif
- // Linux
- #ifndef WIN32
- #define OP_SOCKET int
- #define OP_SOCKADDR_IN struct sockaddr_in
- #define OP_SOCKADDR struct sockaddr
- #define OP_SOCKLEN_T socklen_t
- // Windows
- #else
- #define OP_SOCKET SOCKET
- #define OP_SOCKADDR_IN SOCKADDR_IN
- #define OP_SOCKADDR SOCKADDR
- #define OP_SOCKLEN_T int FAR
- #endif
- #define OP_PORT 8888
- #define BUFFER_SIZE 1024
- #define LISTEN_QUEUE 20
- #define MD5_SIZE 32
- #define FILE_PATH_MAX_SIZE 512
- #define FILE_NAME_MAX_SIZE 260
- #define FILE_FULL_NAME_MAX_SIZE 1024
- #define HOST "localhost"
- #define DEFAULT_SERVER_IP "127.0.0.1"
- #ifndef WIN32
- #define CLI_FILE_PATH "/tmp/data/client/" // 客户端存储文件的初始化路径
- #define SERV_FILE_PATH "/tmp/data/server/" // 服务器端存储文件的初始化路径
- #else
- #define CLI_FILE_PATH "D://download//" // 客户端存储文件的初始化路径
- #define SERV_FILE_PATH "D://data//" // 客户端存储文件的初始化路径
- #endif
- // 把一段内存区的内容全部设置为
- void op_clean_buffer(void *buffer, int len);
- // 设置sockaddr_in, internet协议族, INADDR_ANY表示自动获取本机地址
- void op_set_sockaddr_in(OP_SOCKADDR_IN &addr, short op_sin_family, unsigned long op_s_addr, unsigned short op_sin_port);
- // 创建用于internet的流协议(TCP)socket, 用server_socket代表服务器socket
- int op_socket(int domain, int type, int protocol);
- // 接受一个到server_socket代表的socket的一个连接
- // 如果没有连接请求,就等待到有连接请求--这是accept函数的特性
- // accept函数返回一个新的socket, 这个socket(new_server_socket)用于同连接到的客户的通信
- // new_server_socket代表了服务器和客户端之间的一个通信通道
- // accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中
- int op_accept(OP_SOCKET sockfd, OP_SOCKADDR *addr, OP_SOCKLEN_T *addrlen);
- // IP的点分十记转化为IP的结构体
- unsigned long op_inet_addr(const char *dst);
- // 向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
- int op_connect(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen);
- // addr指定的地址分配给与文件描述符socket关联的未命名套接字
- int op_bind(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen);
- // 监听client请求,backlog指定最大连接数
- int op_listen(OP_SOCKET sockfd, int backlog);
- // send发送消息
- int op_send(OP_SOCKET sockfd, const char *buffer, size_t len, int flags);
- // recv接收消息
- int op_recv(OP_SOCKET sockfd, char *buffer, size_t len, int flags);
- // 关闭socket或文件指针
- FILE* op_fopen(const char *path, const char *mode);
- // 打开文件
- int op_close(OP_SOCKET sockfd);
- // 关闭文件指针
- int op_fclose(FILE *stream);
- // 休眠函数
- void op_sleep(int micro_seconds);
- // 字符串比较函数
- int op_stricmp(char *s1,char * s2);
- #endif
op_socket.cpp源文件代码:
[cpp]
view plain
copy
- #include "op_socket.h"
- // 把一段内存区的内容全部设置为
- void op_clean_buffer(void *buffer, int len)
- {
- #ifndef WIN32
- bzero(buffer, len);
- #else
- memset(buffer, 0, len);
- #endif
- }
- // 设置sockaddr_in
- void op_set_sockaddr_in(OP_SOCKADDR_IN &addr, short op_sin_family, unsigned long op_s_addr, unsigned short op_sin_port)
- {
- op_clean_buffer(&addr, sizeof(addr));
- addr.sin_family = op_sin_family;
- addr.sin_addr.s_addr = op_s_addr;
- addr.sin_port = op_sin_port;
- }
- // 创建socket
- int op_socket(int domain, int type, int protocol)
- {
- int sockfd;
- #ifndef WIN32
- if ((sockfd = socket(domain, type, protocol)) < 0)
- #else
- if ((sockfd = socket(domain, type, protocol)) == INVALID_SOCKET)
- #endif
- {
- fprintf(stderr, "op_socket error/n");
- exit(EXIT_FAILURE);
- }
- return sockfd;
- }
- // 接收客户端的socket请求
- int op_accept(OP_SOCKET sockfd, OP_SOCKADDR *addr, OP_SOCKLEN_T *addrlen)
- {
- int ret;
- if ((ret = accept(sockfd, addr, addrlen)) < 0)
- {
- fprintf(stderr, "op_accept error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // IP的点分十记转化为IP的结构体
- unsigned long op_inet_addr(const char *dst)
- {
- long ret;
- if ((ret = inet_addr(dst)) < 0)
- {
- fprintf(stderr, "op_inet_addr error for %s/n", dst);
- exit(EXIT_FAILURE);
- }
- return (unsigned long)ret;
- }
- // sockfd指定的套接字连接到addr指定的服务器套接字
- int op_connect(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen)
- {
- int ret;
- if ((ret = connect(sockfd, addr, addrlen)) < 0)
- {
- fprintf(stderr, "op_connect error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // addr指定的地址分配给与文件描述符socket关联的未命名套接字
- int op_bind(OP_SOCKET sockfd, const OP_SOCKADDR *addr, OP_SOCKLEN_T addrlen)
- {
- int ret;
- if ((ret = bind(sockfd, addr, addrlen)) < 0)
- {
- fprintf(stderr, "op_bind error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // 监听client请求,backlog指定最大连接数
- int op_listen(OP_SOCKET sockfd, int backlog)
- {
- int ret;
- if ((ret = listen(sockfd, backlog)) < 0)
- {
- fprintf(stderr, "op_listen error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // send发送消息
- int op_send(OP_SOCKET sockfd, const char *buffer, size_t len, int flags)
- {
- int ret;
- if ((ret = send(sockfd, buffer, len, flags)) < 0)
- {
- fprintf(stderr, "op_send error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // recv接收消息
- int op_recv(OP_SOCKET sockfd, char *buffer, size_t len, int flags)
- {
- size_t ret;
- op_clean_buffer(buffer, len);
- if ((ret = recv(sockfd, buffer, len, flags)) < 0)
- {
- fprintf(stderr, "op_recv error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // 关闭socket或文件指针
- int op_close(OP_SOCKET sockfd)
- {
- int ret;
- #ifndef WIN32
- if ((ret = close(sockfd)) < 0)
- #else
- if((ret = closesocket(sockfd)) < 0)
- #endif
- {
- fprintf(stderr, "op_close error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // 打开文件
- FILE* op_fopen(const char *path, const char *mode)
- {
- FILE *fp = fopen(path, mode);
- if (NULL == fp)
- {
- printf("File:/t%s Can Not Open To Write/n", path);
- exit(EXIT_FAILURE);
- }
- return fp;
- }
- // 关闭文件指针
- int op_fclose(FILE *stream)
- {
- int ret;
- if ((ret = fclose(stream)) < 0)
- {
- fprintf(stderr, "op_fclose error/n");
- exit(EXIT_FAILURE);
- }
- return ret;
- }
- // 休眠函数,对于usleep为微秒级别,对于Sleep为毫秒级别
- void op_sleep(int micro_seconds)
- {
- #ifndef WIN32
- usleep(micro_seconds);
- #else
- Sleep(micro_seconds);
- #endif
- }
- // 字符串比较函数
- int op_stricmp(char *s1,char * s2)
- {
- #ifndef WIN32
- return strcasecmp(s1, s2);
- #else
- return stricmp(s1, s2);
- #endif
- }
六、完成了上述的操作之后,就可以分别对client和server端进行编译了,先启动server端服务器,然后用命令行的形式运行client端,就可以成功了吧。哈哈!我们来看一下使用protobuf进行socket通信的实际效果!给大家截个图!
最近项目紧,没空时间来好好写博客,只能粗略记录一下,等实习结束后,要把这段时间的所学所感好好总结下来。
顺便说一下,op_socket这个SOCKET是跨平台的,写个makefile可以直接在UNIX环境下运行的,咳咳,写的太龊了大家见笑了。。。
http://blog.csdn.net/monkey_d_meng/article/details/5894910