RFCOMM |如何在客户端断开连接并向客户端写入数据时收到通知?

时间:2016-08-02 08:02:12

标签: android ios linux bluetooth rfcomm

我在linux端使用RFCOMM Server应用程序,因此任何移动应用程序都可以与它连接并进行通信。 我已经使用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;
}
  1. 在这里,我可以很好地连接并从BlueTerm Android App发送数据。但是当我从设备断开与android的连接时,我不确定我的linux应用程序是否可以检测到客户端已断开连接,因此我可以通过关闭当前活动会话将其重新接受接受新的连接模式?
  2. 我也不确定哪个回复客户端的正确方法是这个函数写回客户端?
  3. status = write(s, &buf, 1);

2 个答案:

答案 0 :(得分:1)

如果客户端已断开连接,则

read(client, buf, sizeof(buf))返回-1。 因此,只要bytes_read大于或等于零,循环就会在循环退出时重新创建服务器。

我已经重写了你的主要功能,将while循环包装在另一个循环中,直到从蓝牙设备收到'x'为止。

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;
}

答案 1 :(得分: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