C++Builder使用TCP发送数组

C++Builder使用TCP发送数组,c++,tcp,c++builder,C++,Tcp,C++builder,在C++Builder中,我必须发送一个多维int数组,如: 使用TCP协议 我使用以下视频创建了一个套接字: 但我不明白如何只发送多维数组而不是字符串。。。有什么提示吗 客户端代码: //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //-----------------

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

使用TCP协议

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

但我不明白如何只发送多维数组而不是字符串。。。有什么提示吗

客户端代码:

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

#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();
}
//---------------------------------------------------------------------------

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

IdTCPClient1->WriteBuffer(&example, sizeof(example));
但是,如果您不想依赖于此,则可以使用TIdTCPConnection::WriteInteger和TIdTCPConnection::ReadInteger方法分别发送/接收int值,例如:

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
        IdTCPClient1->WriteInteger(example[i][j]);
}
如果改为使用动态分配的数组,则可以在发送实际整数之前发送各个维度,这样接收器就会知道预期的整数数量,从而可以分配合适的数组来接收它们,例如:

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]);
}
也就是说,您所展示的代码有几个问题

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

您的客户机正在发送一个长度前缀为AnsiString,后跟一个not count前缀为TStringList。然后,它读取一个长度前缀AnsiString

您的服务器正在正确读取以AnsiString为前缀的客户端长度,但忽略了客户端的TStringList。然后,它发送一个AnsiString的长度,但不发送AnsiString本身,后跟前缀为TStringList的not count。客户端将无法正确读取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();
}
//---------------------------------------------------------------------------

您尚未显示所有代码。什么是IdTCPClient1?请参阅并考虑创建一个以改进您的问题。它只是C++ Builder的一个组件,如果您从Indy客户端选择TCP客户端,IDTCPclient 1是标准名称:明白了,但是省略这一点,对于那些没有C++ Builder的人来说,很难或不可能,并且没有很多额外的时间来观看YouTube视频,比如我自己来帮助你诊断问题。@蓝发FFY,你的代码是使用了9年,这已经超过十年了。考虑升级到印地10。
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();
}
//---------------------------------------------------------------------------

#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();
}
//---------------------------------------------------------------------------