rmds Ответов: 0

Как попросить сервер создать файл с определенным именем с клиентского конца в программировании MFC csocket?


- Привет! Я переношу файлы из папки серверного приложения в папку клиентского приложения один раз после установления соединения. Я даю имя файла для создания нового текстового файла в клиентской программе. Вместо этого я хочу, чтобы сервер отправлял любое сообщение или команду, чтобы попросить клиента создать новый текстовый файл с определенным именем.

Что я уже пробовал:

Это код в клиентском конце, где я даю имя файла для создания.
int br=SockConnection.Прием(бафф,1000);
То Cfile Его Доствили;
Его доствили.Open(L"Myreceivedfile", CFile::modeCreate | CFile::modeWrite);
Его доствили.Пиши (бафф,БР);

Вместо этого я хочу, чтобы сервер проинформировал клиента о создании файла с определенным именем. Пожалуйста, помогите. Спасибо.

Richard MacCutchan

Попросите сервер отправить имя файла в качестве первого сообщения.

rmds

Пожалуйста, поправьте меня, если я ошибаюсь. Вы хотите сказать, что это так?
-SockConnection.Send(L"Myinputfiledata", 0);"

Richard MacCutchan

Как бы. Но вы должны убедиться, что и клиент, и сервер понимают, о чем идет речь в каждом сообщении. Поэтому сообщение с именем файла должно содержать какой-то идентификатор, чтобы его не приняли за обычные данные. Вы должны разработать протокол между вашими терминалами, чтобы они могли проверять информацию, передаваемую между ними. Не думайте, что содержание сообщения-это то, что вы думаете, что оно должно быть.

rmds

Объяснение кристально ясно! Допустим, у меня есть несколько Receive() в клиентском приложении, и мне нужно отправить сообщение или данные с сервера. Как отправить сообщение конкретному Receive()? Я действительно погуглил примеры, но безуспешно. Пожалуйста, пролейте немного света на этот пример. Спасибо!

Richard MacCutchan

Я уже объяснил, что вам нужно сделать. Каждое сообщение должно содержать заголовок, определяющий его содержание. Итак, чтобы запустить новый файл, отправьте сообщение с заголовком и именем файла. Чтобы отправить некоторое содержимое файла, отправьте заголовок плюс некоторые данные. Заголовок должен содержать флаг, определяющий тип записи, и поле длины, сообщающее получателю, какой длины сообщение.

Rick York

Чтобы развить то, что написал Ричард, в предыдущем поколении моего приложения было несколько серверов, которые мы просили выполнять задачи, и они были связаны с сокетами. Каждое сообщение, отправленное им, имело заголовок, который имел несколько байтов версии, длину сообщения и команду. Команда указала серверу, что делать с данными сообщения. Одна команда сообщила серверу, что сообщение содержит копию приложения и ему необходимо обновить себя. Это был интересный маленький процесс. Во всяком случае, я рекомендую принять нечто подобное : включить заголовок в сообщение, чтобы сказать другой стороне, что делать с данными.

rmds

Я понимаю, но на самом деле я никогда этого не делал. Я пытаюсь со вчерашнего дня, но не могу найти, как выглядит send() с заголовком команды. Может ли по крайней мере показать мне проблеск send() с заголовком команды с любым примером? Большое спасибо.

Rick York

send принимает указатель на символьный буфер и длину, поэтому вам нужно собрать символьный буфер для отправки. Memcpy ваш заголовок в начало буфера и следуйте за ним с данными. Вы делаете обратное на другом конце. Memcpy запускает буфер в ваш заголовок, а затем данные следуют за заголовком. Вы знаете, насколько велик заголовок, поэтому вы знаете, где найти данные. Кроме того, вы можете использовать потоки, чтобы настроить его и распаковать на другом конце.

rmds

Пройдя через многое, я сделал вот что...
Сервер:
структура typedef{
char* filename[20];
}буфер данных;
Data_Buffer data_buffer;
буфер данных.filename[21] = "myinputfile";

int nRet = SockConnection.Send((void*)&data_buffer, sizeof(data_buffer));

Клиент:
структура typedef{
char* filename[21];
}буфер данных;
Data_Buffer data_buffer;
int nRet = SockConnection.Receive((void*)&data_buffer, sizeof(data_buffer));
То Cfile Его Доствили;
CString filename = (LPCTSTR)&data_buffer;
Его доствили.Open(filename, CFile::modeCreate | CFile::modeWrite);
Его доствили.Писать(через буфер, БР);

Я получаю имя файла как мусорные значения.. Что пошло не так?

Rick York

Ваши определения неверны. Вы не можете отправить указатель через сокет и предположить, что он действителен, и массив указателей тоже не будет работать. Мой заголовок содержит четыре байта версии, поле длины сообщения и поле команды. Вот и все. Все должно быть статическими данными без указателей. Длина сообщения важна, потому что если у вас есть более 1500 байт данных, они должны будут идти в нескольких пакетах, и длина скажет вам, сколько вам нужно получить.

rmds

Не могли бы вы дать мне представление о заголовке, на который вы ссылаетесь, с сообщением, длиной и командой. Просто хочу посмотреть, как это выглядит, чтобы получить идею для реализации. Спасибо

Rick York

typedef struct
{
   size_t length;
   INT    command;
   UCHAR  version[4];
} MsgHeader;

rmds

Я действительно ценю ваше время для этого. Не могли бы вы пояснить, что именно вы подразумеваете под заголовком? :
typedef struct COMMAND_HEADER {
char* SET_FILE_NAME;
int data_size;
}
пожалуйста поправьте меня если я ошибаюсь

rmds

Спасибо вам, Рик и Ричард!

0 Ответов