android/Bluetooth

L2CAP을 이용한 Socket Programming Note

깍수 2014. 8. 21. 15:57

- MTU

아래와 같이 set/getsockeopt() 함수를 이용하면 MTU(Maximum Transmission Unit) 값을 변경할 수 있으며

해당 Local socket에서만 적용이 된다. Server or Client 각각 이를 설정해야 값을 지정할 수 있다.

기본 MTU 값은 672 Bytes이며 최소 48  Bytes에서 최대 65,535 Bytes까지 적용하 수 있다.

struct l2cap_options {

uint16_t omtu;

uint16_t imtu;

uint16_t flush_to;

uint8_t mode;

};

 

int set_l2cap_mtu( int sock, uint16_t mtu ) { struct l2cap_options opts; int optlen = sizeof(opts), err; err = getsockopt( s, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen ); if( ! err ) { opts.omtu = opts.imtu = mtu; err = setsockopt( s, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen ); } return err; };


* 용어 정리

PSM : Protocol Service Multiplexer

L2CAP socket에서 사용가능한 Port는 4097~32,767(0x1001-0x7FFF)까지 홀수 번호이다.


ex) L2CAP Server&Client

1) Server

#include <stdio.h>
#include <string.h>

#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>

int main(int argc, char **argv)
{
    struct sockaddr_l2 loc_addr = { 0 }, rem_addr = { 0 };
//  struct l2cap_options opts;

    char buf[1024] = { 0 };
    int s, client, bytes_read, optlen;
    socklen_t opt = sizeof(rem_addr);

    // allocate socket
    s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);

    // bind socket to port 0x1001 of the first available
    // bluetooth adapter
    loc_addr.l2_family = AF_BLUETOOTH;
    loc_addr.l2_bdaddr = *BDADDR_ANY;
    loc_addr.l2_psm = htobs(0x1001);

    bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

//  optlen = sizeof(opts);
//  getsockopt(s, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen);
//  printf("before omtu = %d, imtu = %d\n", opts.omtu, opts.imtu);

    // put socket into listening mode
    listen(s, 1);

    // accept one connection
    client = accept(s, (struct sockaddr *)&rem_addr, &opt);

//  optlen = sizeof(opts);
//  getsockopt(s, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen);
//  printf("after omtu = %d, imtu = %d\n", opts.omtu, opts.imtu);

    ba2str( &rem_addr.l2_bdaddr, buf );
    fprintf(stderr, "accepted connection from %s\n", buf);

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

    // close connection
    close(client);
    close(s);


2) Client

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>

int set_l2cap_mtu( int sock, uint16_t mtu );

int main(int argc, char **argv)
{
    struct sockaddr_l2 addr = { 0 };
    int s, status;
    char *message = "hello!";
    char dest[18] = "01:23:45:67:89:AB";

    struct l2cap_options opts;
    int optlen;

    if(argc < 2)
    {
        fprintf(stderr, "usage: %s <bt_addr>\n", argv[0]);
        exit(2);
    }

    strncpy(dest, argv[1], 18);

    // allocate a socket
    s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);

    set_l2cap_mtu(s, 65535);

    // set the connection parameters (who to connect to)
    addr.l2_family = AF_BLUETOOTH;
    addr.l2_psm = htobs(0x1001);
    str2ba( dest, &addr.l2_bdaddr );

    // connect to server
    status = connect(s, (struct sockaddr *)&addr, sizeof(addr));

    optlen = sizeof(opts);
    getsockopt(s, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen);
    printf("after omtu = %d, imtu = %d\n", opts.omtu, opts.imtu);

    // send a message
    if( status == 0 ) {
        status = write(s, "hello!", 6);
    }

    if( status < 0 ) perror("uh oh");

    close(s);
}

int set_l2cap_mtu( int sock, uint16_t mtu ) {
    struct l2cap_options opts;
    int optlen = sizeof(opts), err;

    err = getsockopt( sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen );
    if( ! err ) {
        printf(" current omtu = %d, imtu = %d\n", opts.omtu, opts.imtu);
        opts.omtu = opts.imtu = mtu;
        err = setsockopt( sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen );
    }

    return err;
}


춮처 : Bluetooth Essentials