在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();
}
//---------------------------------------------------------------------------
答案 0 :(得分:1)
无论数组使用多少维度,它仍然具有固定的字节大小(sizeof(int) * 3 * 3 = 36
),因此您可以使用TIdTCPConnection::WriteBuffer()
和TIdTCPConnection::ReadBuffer()
方法发送/接收它,例如:
IdTCPClient1->WriteBuffer(&example, sizeof(example));
AThread->Connection->ReadBuffer(&example, sizeof(example));
但是,如果您不想依赖它,那么您可以使用int
和TIdTCPConnection::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();
}
//---------------------------------------------------------------------------