网络大数运算之传输表达式和结果

原创 2016年08月30日 19:57:50

客户端每次可以发送一个表达式到客户端,客户端解析该表达式字符串,进行相应的运算结果求解。客户端表达式传输采用结构体,结构体定义如下:

typedefstruct node{
    char bigData1[MAX_BUF]; // Data1
    char bigData2[MAX_BUF]; // Data2
    char opera;             // 运算符
}Expression;

由于使用TCP协议进行传输,采用send()发送字符流,需要对结构体指针转化为char*,发送一个字符流。但因为结构体内存对齐原因,两个变量之间可能存在空白区,这样会造成服务端在解析该字符流的时候,会出现乱码的情况。因此使用#pragma pack(1)将对齐的字节数为1字节,这样转化为字符流时,每个变量是连续存储的。服务端也需要定义相同的结构体接收该字符流。

1. 服务端

(1) 初始化监听套接字和套接字地址,然后将监听套接字与IP地址,端口进行绑定。然后监听8888端口。

void BigIntSocket::InitBigIntSocket() {

    BigIntSocket::ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (ListenSocket < 0) {
        close(ListenSocket);
        err_sys("socket error");
    }
    bzero(&BigIntSocket::ServerAddr, sizeof(BigIntSocket::ServerAddr));
    BigIntSocket::ServerAddr.sin_family = AF_INET;
    BigIntSocket::ServerAddr.sin_port = htons(8888);
    BigIntSocket::ServerAddr.sin_addr.s_addr = inet_addr("192.168.59.154");

}

void BigIntSocket::Bind() {
    
    if (bind(BigIntSocket::ListenSocket, (struct sockaddr*)&BigIntSocket::ServerAddr, sizeof(BigIntSocket::ServerAddr)) < 0) 
    {
        close(ListenSocket);
        err_quit("bind error");
    }        
}

void BigIntSocket::Listen() {
    
    if (listen(BigIntSocket::ListenSocket, MAX_LINE) < 0) 
        err_quit("listen error");
} 

(2) 使用accept()等待客户端的连接。

int BigIntSocket::Accept() {

    socklen_t sock_len = sizeof(ClientAddr);
    bzero(&ClientAddr, sock_len);
    ConnectSocket = accept(BigIntSocket::ListenSocket, (struct sockaddr*)&ClientAddr, &sock_len);
    if (ConnectSocket < 0) 
        err_quit("accept error");
}

(3) 接收字符流,对Exp结构体成员进行赋值。使用Datalength1和Datalength2统计每次接收data1和data2的字符个数。每次接收时需要对Datalength1和Datalength2初始化为0,防止同一个客户端多次请求,造成字符长度的累加,使得结果错误。

void BigIntSocket::Recv() {

    memset(Recvbuf, 0, sizeof(Expression));
    memset(Exp.bigData1, 0, MAX_BUF);
    memset(Exp.bigData2, 0, MAX_BUF);
    Exp.opera = 0;
   // 长度初始化0
    Datalength1 = 0;
    Datalength2 = 0;  
    len = recv(ConnectSocket, Recvbuf, 3 * MAX_BUF, 0);// 接收字符流
    if (len < 0) 
        err_sys("recv error");
    unsigned int i;
    for (; Recvbuf[Datalength1] != '\0'; ++Datalength1) 
        Exp.bigData1[Datalength1] = Recvbuf[Datalength1];
    for (i = MAX_BUF; i < 2 * MAX_BUF && Recvbuf[i] != '\0' ; ++i) 
        Exp.bigData2[Datalength2++] = Recvbuf[i];
    
    Exp.opera = Recvbuf[2 * MAX_BUF];
    //cout << Exp.bigData1 << ' ' << Exp.bigData2 << ' ' << Exp.opera;
}

(4) 对表达式进行计算。表达式存储在服务端的Exp结构体中,初始化BigInt的两个对象b1和b2,b1和b2成员为SeqList<char>,然后将Data1和Data2 使用push_back存放到SeqList<char>中。由于Recvbuf中存的是字符,所以需要减去字符0。然后根据Exp.opera选择相应的表达式进行(这里只列举了简单的加、减、乘、除的运算)。计算完毕后,将计算结果b3复制到Sendbuf缓冲区中。

void BigIntSocket::Processing() {

    BigInt b1(MAX_BUF);
    BigInt b2(MAX_BUF);
    BigInt b3(MAX_BUF * 2);
    int i, j;

    b1.push_back(0);
    b2.push_back(0);
    for (i = Datalength1 - 1; i >= 0; --i)
        b1.push_back(Exp.bigData1[i] - '0'); 
    for (j = Datalength2 - 1; j >= 0; --j) 
        b2.push_back(Exp.bigData2[j] - '0');
  // BigInt已重载过下列运算符和赋值运算符
  switch(Exp.opera) {
        case '+':
            b3 = b1 + b2;  
            break;
        case '-':
            b3 = b1 - b2;
            break;
        case 'x':
            b3 = b1 * b2;
            break;
        case '/':
            b3 = b1 / b2;
            break;
        default:
            err_quit("no operator");
            break;
    }
    j = 0;
    memset(Sendbuf, 0, 2 * MAX_BUF); 
    for (i = b3.size() - 1; i >= 1; --i) 
        Sendbuf[j++] = b3[i] + '0';   // 转化为字符
    cout << Sendbuf << endl;
}

(5) 发送字符流到客户端。

void BigIntSocket::Send() {
    
    if (send(ConnectSocket, Sendbuf, strlen(Sendbuf), 0) < 0) 
        err_sys("send error");
}

1. 客户端

(1) 初始化套接字地址。

void BigIntSocket::InitBigIntSocket() {
    
    bzero(&BigIntSocket::ServerAddr, sizeof(BigIntSocket::ServerAddr));
    BigIntSocket::ServerAddr.sin_family = AF_INET;
    BigIntSocket::ServerAddr.sin_port = htons(8888);
    BigIntSocket::ServerAddr.sin_addr.s_addr = inet_addr("192.168.59.154");
}

(2) 发送连接请求,与服务端建立连接。

void BigIntSocket::Connect() {
    
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket < 0) 
        err_sys("socket error");

    if (connect(ConnectSocket, (struct sockaddr*)&BigIntSocket::ServerAddr, sizeof(BigIntSocket::ServerAddr)) < 0) {
        
        close(ConnectSocket);
        err_quit("connect error");
    }
}

(3) 发送表达式字符流

void BigIntSocket::Send(const char* big1, const char* opera, const char* big2) {
    // main函数使用命令行参数接收表达式,在命令行乘号不能用’*’表示
    if (big1 && opera && big2) {
        strcpy(Exp.bigData1, big1);
        Exp.opera = *opera;
        strcpy(Exp.bigData2, big2);
    }

    if ((len = send(ConnectSocket, (char*)&Exp, sizeof(Exp), 0)) < 0) 
        err_sys("send error");
}

(4) 接收计算结果

void BigIntSocket::Recv() {
    
    if (recv(ConnectSocket, Recvbuf, len, 0) < 0) 
        err_sys("recv error");

    cout << Recvbuf << endl;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

【网络协议】TCP分段与UDP/IP分片 (MTU最大传输单元,MSS最大分段大小)

我们在学习TCP/IP协议时都知道,TCP报文段如果很长的话,会在发送时发生分段,在接受时进行重组,同样IP数据报在长度超过一定值时也会发生分片,在接收端再将分片重组。     我们先来看两个与TC...
  • xiexievv
  • xiexievv
  • 2015年04月23日 19:46
  • 4009

数据传输过程(FTP 但不限于FTP)详解--- 网络传输

一、FTP客户端发送数据到FTP服务器端,详述其工作过程。两台机器的连接情况如下图所示: 1.1、假设初始设置如下所示: 客户端FTP端口号为:32768 服务器端FTP端口号为:21 ...
  • zhuimengfuyun
  • zhuimengfuyun
  • 2013年11月18日 21:12
  • 2373

java的运算符,表达式和语句

java的运算符基本与c语言相似,算术运算符是+,-,*,/和%,用法与c语言一样。算术的运算精度从低到高有byte,short,char,int,long,float,double。关系运算符有>,...
  • yt2054
  • yt2054
  • 2016年03月08日 12:55
  • 340

RSA与大数运算(基本原理剖析)

http://jcwondrous.spaces.live.com/blog/cns!5B208B2E6D12F6AF!361.trak RSA 依赖大数运算,目前主流RSA算法都建立在512 到10...
  • pungin
  • pungin
  • 2010年08月17日 12:02
  • 953

【JAVA开发之IO流1-4】IO流之数据流与网络传输基础

在我们的实际开发中经常要将String、Long等形式的数据进行网络传输,这就需要将这些String等形式的数据,转化为字节数组byte[],再进行网络传输,传输后进行解码,还原成String等形式,...
  • qq_33706077
  • qq_33706077
  • 2016年03月29日 14:04
  • 814

请选择结果为真的表达式

请选择结果为真的表达式:()A.null instanceof ObjectB.null===undefinedC.null==undefinedD.NaN==NaN为什么?...
  • JAVA1135720461
  • JAVA1135720461
  • 2011年04月21日 23:22
  • 2211

表达式的期望值

gcc的内建函数__builtin_expect 在内核代码的条件分支中的判断中,经常可以看到如下两条语句: /* ...... */ if(unlikely(!something))...
  • ylo523
  • ylo523
  • 2015年02月03日 14:38
  • 280

网络传输中,文本文件与二进制文件

今天写Walker的网络传输, 在传输文件时, 出现一点问题。 1.如果传输文本文件, 只要一个字节一个字节地对应传送过去即可。 2.如果传输二进制文件,也只要一个字节一个字节传送过去就可以。。 读写...
  • a576323437
  • a576323437
  • 2014年01月23日 02:04
  • 3076

【java解惑】条件表达式结果类型规则

如下代码:public class Example008 { public static void main(String[] args) { char x = 'X'; int i = 0...
  • imu2008
  • imu2008
  • 2015年11月04日 08:41
  • 385

表达式得到期望结果的组成种数

/************************************************************************************  *description...
  • yoomiky
  • yoomiky
  • 2017年08月12日 01:08
  • 98
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:网络大数运算之传输表达式和结果
举报原因:
原因补充:

(最多只允许输入30个字)