РФКОММ | Как получить уведомление, когда Клиент отключается, и записать данные клиенту?
Я использую приложение RFCOMM Server на стороне Linux, чтобы любое мобильное приложение могло подключиться к нему и установить связь. Я использовал пример rfcomm-server.c для тестирования и немного изменил его
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read, status;
socklen_t opt = sizeof(rem_addr);
void vCreateConnection()
{
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
}
void vCloseConnection()
{
close(client);
close(s);
}
int main(int argc, char **argv)
{
vCreateConnection();
while(1)
{
printf("\r\nClear buffer");
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
//if(status == 0)
{
printf("send [%s]\n", buf);
status = write(s, &buf, 1);
//status is not making any difference.
//if(status < 0)
//break;
}
}
if(buf[0] == 'q')
{
vCloseConnection();
vCreateConnection();
}
else if(buf[0] == 'x')
break;
}
// close connection
close(client);
close(s);
return 0;
}
- Здесь я могу подключиться и отправлять данные из Android-приложения BlueTerm. Но когда я отключаюсь от устройства от Android, я не уверен, что мое приложение linux может обнаружить, что клиент отключен, и я могу вернуть его в режим принятия нового подключения, закрыв текущий активный сеанс?
- Я также не уверен, что это правильный способ ответить клиенту, эта функция для обратной записи клиента?
status = write(s, &buf, 1);
1 ответ
read(client, buf, sizeof(buf))
возвращает -1, если клиент отключился. Итак, цикл до тех пор, пока bytes_read
больше или равно нулю и воссоздает сервер после выхода из цикла.
Я переписал вашу основную функцию, включив цикл while в другой цикл, который выполняется до тех пор, пока "x" не будет получено от устройства Bluetooth.
int recreate_connection=1;
int main(int argc, char **argv)
{
while(recreate_connection==1)
{
vCreateConnection();
bytes_read=0;
while(bytes_read >=0)
{
printf("\r\nClear buffer");
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
//if(status == 0)
{
printf("send [%s]\n", buf);
status = write(s, &buf, 1);
//status is not making any difference.
//if(status < 0)
//break;
}
}
if(buf[0] == 'q')
{
vCloseConnection();
break;
}
else if(buf[0] == 'x')
{
recreate_connection=0;
break;
}
}
}
// close connection
close(client);
close(s);
return 0;
}
Чтобы добавить к ответу @Avinab Malla, -1 не означает, что узел обязательно отключился. Это важно отметить, потому что, если вы используете неблокирующий сокет, вы всегда получите -1, если нечего читать, с ошибкой (EWOULDBLOCK). В этом случае вы не хотите разрывать петлю. Вы можете найти все системные ошибки Linux здесь: http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html. Чтобы правильно обрабатывать -1 при чтении, я предложу что-то вроде этого:
do {
memset(comBuffer, 0, sizeof(comBuffer));
// read data from the client
bytesRead = read(clientSockDescriptor, comBuffer, sizeof(comBuffer));
if (bytesRead < 1) {
if (errno == EWOULDBLOCK) {
continue;
}
else {
//You can either exit you read loop here or check the error for something specific
// A peer reset (the client disconneted ) is error: ECONNRESET
printf("A read error occured %d \n", errno);
break;
}
}
// Processes your buffer here.....
} while (clientSockDescriptor != -1 && runComServer); //The while you have your true clause