C ++ Builder使用TCP发送数组

时间:2018-04-25 15:42:04

标签: c++ tcp c++builder

在C ++ Builder中,我必须发送一个int的多维数组,如:

int example[3][3];

使用TCP协议。

我使用此视频创建了一个套接字:

https://www.youtube.com/watch?v=UjrITeDk718

但是我不明白如何只发送一个多维数组而不是字符串...任何提示?

客户代码:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  IdTCPClient1->Connect();
  //send byte
  IdTCPClient1->WriteInteger(Edit1->Text.Length());
  //send text
  IdTCPClient1->Write(Edit1->Text);


  //send request
  TStringList *SL = new TStringList;
  SL->Add(Edit1->Text);
  IdTCPClient1 ->WriteStrings(SL);
  delete SL;
  ListBox1->Items->Add(Edit1->Text+">>sent");


  int bytes = IdTCPClient1 -> ReadInteger();
  AnsiString resp = IdTCPClient1->ReadString(bytes);
  ListBox1->Items->Add(resp);
  IdTCPClient1->Disconnect();

}
//---------------------------------------------------------------------------

服务器代码:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
  int bytes =  AThread->Connection->ReadInteger();

  AnsiString request = AThread->Connection->ReadString(bytes);
  ListBox1->Items->Add(request);

  Edit1->Text=FormatDateTime("hh:mm AM/PM", Now());
  AnsiString risp = Edit1->Text;

  AThread->Connection->WriteInteger(risp.Length());
  TStringList *SL = new TStringList;
  SL->Add(risp);
  AThread->Connection->WriteStrings(SL);
  delete SL;
  ListBox1->Items->Add(risp+">> inviato");
  AThread->Connection->Disconnect();
}
//---------------------------------------------------------------------------

1 个答案:

答案 0 :(得分:1)

无论数组使用多少维度,它仍然具有固定的字节大小(sizeof(int) * 3 * 3 = 36),因此您可以使用TIdTCPConnection::WriteBuffer()TIdTCPConnection::ReadBuffer()方法发送/接收它,例如:

IdTCPClient1->WriteBuffer(&example, sizeof(example));

AThread->Connection->ReadBuffer(&example, sizeof(example));

但是,如果您不想依赖它,那么您可以使用intTIdTCPConnection::WriteInteger()方法单独发送/接收TIdTCPConnection::ReadInteger()值,例如:

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
        IdTCPClient1->WriteInteger(example[i][j]);
}

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
        example[i][j] = AThread->Connection->ReadInteger();
}

如果您使用动态分配的数组,则可以在发送实际整数之前发送各个维度,这样接收器就会知道期望的整数数量,因此可以分配合适的数组来接收它们,例如: / p>

IdTCPClient1->WriteInteger(3);
IdTCPClient1->WriteInteger(3);

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
        IdTCPClient1->WriteInteger(example[i][j]);
}

rows = AThread->Connection->ReadInteger();
cols = AThread->Connection->ReadInteger();

example = new int*[rows];
for (int i = 0; i < rows; ++i)
{
    example[i] = new int[cols];
    for (int j = 0; j < cols; ++j)
        example[i][j] = AThread->Connection->ReadInteger();
}

话虽如此,您所展示的代码存在一些问题。

  • 您的客户端和服务器彼此不匹配:

    • 您的客户端正在发送一个以长度为前缀的AnsiString,后跟一个(不是以前计数为前缀的)TStringList。然后读取长度为前缀的AnsiString。

    • 您的服务器正在正确读取客户端的长度前缀AnsiString,但忽略了客户端的TStringList。然后它发送AnsiString的长度,但不发送AnsiString本身,然后是(不计数前缀)TStringList。客户端将无法正确读取TStringList。

  • 访问UI控件时,TIdTCPServer :: OnExecute处理程序未与主UI线程同步。 TIdTCPServer是一个多线程组件,它的事件是在工作线程的上下文中触发的,而不是主UI线程。您必须在从工作线程访问UI时进行同步,否则会发生不好的事情。

请改为尝试:

客户端:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String s = Edit1->Text;

    int example[3][3];
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 3; ++j)
           example[i][j] = (i*3)+j;
    }

    IdTCPClient1->Connect();
    try
    {
        //send byte length
        IdTCPClient1->WriteInteger(s.Length());
        //send text
        IdTCPClient1->Write(s);

        // send array
        IdTCPClient1->WriteBuffer(&example, sizeof(example));

        ListBox1->Items->Add(s + ">>sent");

        int bytes = IdTCPClient1->ReadInteger();
        String resp = IdTCPClient1->ReadString(bytes);
        ListBox1->Items->Add(resp);
    }
    __finally
    {
        IdTCPClient1->Disconnect();
    }
}
//---------------------------------------------------------------------------

服务器:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <IdSync.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
class TAddToListBoxSync : public TIdSync
{
public:
    String str;
    __fastcall TAddToListBoxSync(const String &s) : TIdSync(), str(s) {}
    virtual void __fastcall DoSynchronize() { Form1->ListBox1->Items->Add(str); }
};

class TSetEditTextSync : public TIdSync
{
public:
    String str;
    __fastcall TSetEditTextSync(const String &s) : TIdSync(), str(s) {}
    virtual void __fastcall DoSynchronize() { Form1->Edit1->Text = str; }
};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
    int bytes = AThread->Connection->ReadInteger();
    String request = AThread->Connection->ReadString(bytes);

    int example[3][3];
    AThread->Connection->ReadBuffer(&example, sizeof(example));

    TAddToListBoxSync *lb_sync = new TAddToListBoxSync(request);
    try {
        lb_sync->Synchronize();
    }
    __finally {
        delete lb_sync;
    }

    String risp = FormatDateTime("hh:mm AM/PM", Now());

    TSetEditTextSync *edt_sync = new TSetEditTextSync(risp);
    try {
        edt_sync->Synchronize();
    }
    __finally {
        delete edt_sync;
    }

    AThread->Connection->WriteInteger(risp.Length());
    AThread->Connection->Write(risp);

    lb_sync = new TAddToListBoxSync(risp + ">> inviato");
    try {
        lb_sync->Synchronize();
    }
    __finally {
        delete lb_sync;
    }

    AThread->Connection->Disconnect();
}
//---------------------------------------------------------------------------