Читайте также: |
|
В терминах обмена сообщениями, сервер отрабатывает схему обмена в два этапа:
· этап «приема» (receive);
· этап «ответа» (reply).
Рис.4 Взаимосвязь функций клиента и сервера при обмене сообщениями
Обсудим два простейших варианта соответствующих функций, MsgReceive() и MsgReply().
#include <sys/neutrino.h>
int MsgReceive (int chid,void *rmsg, int rbytes, struct _msg_info *info);
int MsgReply (int rcvid, int status, const void *msg, int nbytes);
Четыре основных элемента:
1 Клиент вызывает функцию MsgSend() и указывает ей на буфер передачи (указателем smsg и длиной sbytes). Данные передаются в буфер функции MsgReceive() на стороне сервера, по адресу rmsg и длиной rbytes. Клиент блокируется.
2 Функция MsgReceive() сервера разблокируется и возвращает идентификатор отправителя rcvid, который будет впоследствии использован для ответа. Теперь сервер может использовать полученные от клиента данные.
3 Сервер завершил обработку сообщения и теперь использует идентификатор отправителя rcvid, полученный от функции MsgReceive(), передавая его функции MsgReply(). Заметьте, что местоположение данных для передачи функции MsgReply() задается как указатель на буфер (smsg) определенного размера (sbytes). Ядро передает данные клиенту.
4 Наконец, ядро передает параметр sts, который используется функцией MsgSend() клиента как возвращаемое значение. После этого клиент разблокируется.
Для каждой буферной передачи указываются два размера (в случае запроса от клиента это sbytes на стороне клиента и rbytes на стороне сервера; в случае ответа сервера это sbytes на стороне сервера и rbytes на стороне клиента). Это сделано для того, чтобы разработчики каждого компонента смогли определить размеры своих буферов — из соображений дополнительной безопасности.
2.3.2 Текст программы
// server.c
#include <stdio.h>
#include <pthread.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/neutrino.h>
void server(void)
{
int rcvid; //Ykazivaet komy nado otvechat
int chid; //Identifikator kanala
char message[512]; //
printf("Server start working \n");
chid=ChannelCreate(0); //Sozdanie Kanala
printf("Chanel id: %d \n", chid);
printf("Pid: %d \n", getpid());
// vipolniaetsa vechno- dlia servera eto normalno
while(1)
{
// Polychit i vivesti soobshenie
rcvid=MsgReceive(chid,message,sizeof(message), NULL);
printf("Polychili soobshenie, rcvid %X \n",rcvid);
printf("Soobshenie takoe: \"%s\". \n", message);
// Podgotovit otvet
strcpy(message,"Eto otvet");
MsgReply(rcvid, EOK, message, sizeof(message));
printf("\"%s\". \n", message);
}
}
int main(void)
{
printf("Prog server \n");
server();
sleep(5);
return(1);
}
//client.c
#include <stdio.h>
#include <pthread.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/neutrino.h>
int main(void)
{
char smsg[20];
char rmsg[200];
int coid;
long serv_pid;
printf("Prog client, Vvedite PID servera \n");
scanf ("%ld",&serv_pid);
printf("Vveli %ld \n", serv_pid);
coid=ConnectAttach(0,serv_pid,1,0,0);
printf("Connect res %d \n, vvedite soobshenie ", coid);
scanf("%s",&smsg);
printf("Vveli %s \n", smsg);
if(MsgSend(coid,smsg,strlen(smsg)+1,rmsg, sizeof(rmsg))==-1)
{
printf("Error MsgSend \n");
}
return(1);
}
2.3.3 Последовательность действий
После компиляции программ сервера и клиента у нас будет 2 исполняемых файла. Назовём их server и client соответственно.
Программу server необходимо запустить в фоновом режиме # server &. Она начнёт работать: создаст канал, выведет номер канала и идентификатор процесса сервера, будет ждать сообщения от клиента.
Потом необходимо запустить клиента. Он попросит ввести идентификатор процесса сервера, для установления соединения с ним, и само сообщение (20 символов). Далее можно наблюдать, как сервер получит сообщение, выведет его и пошлёт ответ.
На этом клиент закончит свою работу, но его можно запустить ещё раз и послать другое сообщение.
Остановить работу сервера можно функцией kill < идентификатор процесса сервера >.
2.3.4 Результаты
# `pwd`/server &
[3] 2019364
# Prog server
Server start working
Chanel id: 1
Pid: 2019364
# `pwd`/client
Prog client, Vvedite PID servera
Vveli 2019364
Connect res 3
, vvedite soobshenie Hello_server
Vveli Hello_server
Polychili soobshenie, rcvid 2
Soobshenie takoe: "Hello_server".
"Eto otvet".
# `pwd`/client
Prog client, Vvedite PID servera
Vveli 2019364
Connect res 3
, vvedite soobshenie I_snova_Privet
Vveli I_snova_Privet
Polychili soobshenie, rcvid 2
Soobshenie takoe: "I_snova_Privet".
"Eto otvet".
# kill 2019364
#
2.4 Лабораторная работа №4 «Тайм - ауты»
2.4.1 Теоретические сведения
Дата добавления: 2015-07-11; просмотров: 118 | Нарушение авторских прав