google protocol buffer协议的socket通信实例

来源:互联网 发布:指纹识别芯片 算法 编辑:程序博客网 时间:2024/05/29 19:19

package lm;

message helloworld

 {

 required int32 id = 1; // ID

required string str = 2; // str

optional int32 opt = 3; //optional field

一个比较好的习惯是认真对待 proto 文件的文件名。比如将命名规则定于如下:

packageName.MessageName.proto 

./protoc -I=/home/hfx/protobuf/bin --cpp_out=/home/hfx/protobuf/bin /home/hfx/protobuf/bin/lm.helloworld.protoc

命令将生成两个文件:

lm.helloworld.pb.h , 定义了 C++ 类的头文件

lm.helloworld.pb.cc , C++ 类的实现文件

在生成的头文件中,定义了一个 C++ 类 helloworld,后面的 Writer 和 Reader 将使用这个类来对消息进行操作。诸如对消息的成员进行赋值,将消息序列化等等都有相应的方法。

=============c++ server reader=====
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "gw.helloworld.protoc.pb.h"
 
#define MAXLINE 100
#define SA struct sockaddr
#define SOCKET int
 
using namespace std;
 
void ListMsg(const gw::helloworld & msg)
{
    cout << msg.id() << endl; cout << msg.str() << endl;
}
 
int main()
{
    cout << "this is a server!" << endl;
    struct sockaddr_in server,client;
 
    SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建监听套接字
    if(listen_sock < 0)
    {
        perror("socket error");
        return -1;
    }
 
    memset((char *)&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(8888);
    if(bind(listen_sock, (SA *)&server, sizeof(server)) < 0) // 绑定监听端口
    {
        perror("bind error");
        return -1;
    }
 
    listen(listen_sock, 5); // 监听 sockfd 一个已绑定未被连接的套接字描述符   backlog 队列
 
    socklen_t n = (socklen_t)sizeof(client);
    SOCKET conn_sock = (SOCKET)accept(listen_sock, (SA *)&client, &n); // 创建连接套接字
    if(conn_sock < 0)
        perror("accept error");
    else
    {
        // 接受client请求信息
        unsigned char buf[MAXLINE+1];
        memset(buf, 0, sizeof(buf));
        if((n = recv(conn_sock, buf, MAXLINE, 0)) < 0)
            perror("recv error");
        else
        {
            gw::helloworld msg2;
            {  
                int length = 100;
                msg2.ParseFromArray(buf,length);
                /*
                if (!msg2.ParseFromIstream(&buf))
                {  
                    cerr << "Failed to parse address book." << endl;
                    return -1;
                }  */
            }  
            ListMsg(msg2);
            cout << "read massage from disk with PB SUCCESS!" << endl;
        }
        // 服务器处理业务///
        //                ////
        ////////////////////
 
        // 返回服务器处理结果字符串
        if(send(conn_sock, "server!", 7, 0) < 0)
            perror("send error");
 
        close(conn_sock);
    }
    close(listen_sock);
    return 0;   
}
=============c++ client writer====
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "gw.helloworld.protoc.pb.h"
 
#define MAXLINE 100
#define SA struct sockaddr
#define SOCKET int
 
using namespace std;
 
const char *ip = {"127.0.0.1"};
const int port = 8888;
 
int main()
{
    cout << "this is a client!" << endl;
    cout << "conn server ip:" << ip << endl;
    cout << "conn server port:" << port << endl;
 
    SOCKET sockfd;
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {// 创建一个套接字,tcp协议,流套接字,通信协议
        perror("socket error");
        return -1;
    }
    struct sockaddr_in servaddr; // 通信地址类型变量
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    struct hostent *hp;
    hp = gethostbyname(ip);
    memcpy((char*)&servaddr.sin_addr, (char*)hp->h_addr, hp->h_length);
 
    if(connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) < 0) // 建立连接
    {
        perror("connect error");
        return -1;
    }
 
    // 打包
    gw::helloworld msg1;
    msg1.set_id(101);
    msg1.set_str("hello world!");
 
    int length = msg1.ByteSize();
    char* buf = new char[length];
    msg1.SerializeToArray(buf,length);
/*
    if (!msg1.SerializeToOstream(&message)) {
        cerr << "Failed to write msg." << endl;
        return -1;
    }  
*/
    cout << "write massage to disk with PB SUCCESS!" << endl;
 
    if(send(sockfd, buf, strlen(buf), 0) < 0) // 发送请求字符串
    {
        perror("send error");
        return -1;
    }
 
    int n;
    char recvline[MAXLINE+1];
    while((n = recv(sockfd, recvline, MAXLINE, 0)) > 0) // 接受,阻塞
    {
        recvline[n] = 0;
        cout << "recv from server: "<< recvline <<endl;
    }
    if(n < 0)
        perror("recv error");
 
    close(sockfd); // 关闭套接字连接
 
    return 0;   
}
=============java server===============
package gw;
 
import gw.GwHelloworldProtoc.helloworld;
 
import java.net.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.io.*;
 
import com.google.gson.Gson;
 
class ServerThread extends Thread {
    Socket socket = null;
 
    ServerThread(Socket socket) {
        this.socket = socket;
    }
 
    public void run() {
 
        try {
            // 接收client发来的消息
            DataInputStream input = new DataInputStream(socket.getInputStream());
            // pb
//            helloworld o = helloworld.parseFrom(input);
//            System.out.println(o.getId() + " " + o.getStr() + " " + o.getOpt());
 
            //json
            byte[] bt = new byte[1024];
            int n = input.read(bt);
            bt[n] = 0;
            String tmp = new String(bt).trim();
            Gson gson = new Gson();
            JMessBean bean = gson.fromJson(tmp, JMessBean.class);
            System.out.println(bean.toString());
 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
}
 
public class Server {
 
    public static int portNo = 3333;
 
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        ServerSocket server = new ServerSocket(portNo);
        while (true) {
            Socket client = server.accept();
            new ServerThread(client).start();
        }
    }
}
============java client=============
package gw;
 
import gw.GwHelloworldProtoc.helloworld;
 
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
 
import com.google.gson.Gson;
 
public class Client {
    public static int portNo = 3333;
 
    public static void main(String[] args) throws IOException {
        InetAddress addr = InetAddress.getByName("localhost");
        Socket socket = new Socket(addr, portNo);
 
        // 像server端发送
        DataOutputStream output = new DataOutputStream(socket.getOutputStream());
 
        // pb打包
        // helloworld o =
        // helloworld.newBuilder().setId(101).setStr("nice to meet you!").setOpt(1).build();
        // System.out.println(o.toByteArray().length);
        // output.write(o.toByteArray());
 
        // json打包
        JMessBean bean = new JMessBean(101, "nice to meet you!", 1);
        Gson gson = new Gson();
        String json = gson.toJson(bean);
        System.out.println(json);
        System.out.println(json.getBytes().length);
        output.write(json.getBytes());
 
        output.flush();
 
        socket.close();
    }
}