C套接字编程:重新打开并重新连接套接字

时间:2016-02-11 16:10:03

标签: c multithreading sockets

我正在测试我的代码以便在连接断开时重新连接。但是,在重新打开并重新连接套接字后,我会遇到一些分段错误。

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>             //socket
#include <bluetooth/bluetooth.h>    //bluetooth
#include <bluetooth/rfcomm.h>       //bluetooth
#include <string.h>                 //strlen
#include <arpa/inet.h>              //inet_addr

struct BTConnection {
   int client;
   int s;
   int retry;
};

struct BTConnection bt_1;

void *bt_connect(void *arg);
void *bt_send(void *arg);
void *bt_receive(void *arg);

void *bt_connect(void *arg)
{
    struct BTConnection *connect = (struct BTConnection*)arg;

    struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
    char buf[1024] = { 0 };
    socklen_t opt = sizeof(rem_addr);

    // allocate socket
    connect->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(connect->s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

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

    // accept one connection
    connect->client = accept(connect->s, (struct sockaddr *)&rem_addr, &opt);
    ba2str( &rem_addr.rc_bdaddr, buf );

    return 0;
}

void *bt_send(void *arg)
{
    struct BTConnection *connect = (struct BTConnection*)arg;
    char buf[1024] = { 0 };
    int bytes_read, retry;

    puts("[Bluetooth] Sending data to device...");
    while(1) {
        .....

        pthread_mutex_lock(&mDataMutex);
        puts("send mutex in");
        while(connect->retry != 0);
        puts("send mutex out");
        pthread_mutex_unlock(&mDataMutex);

        if(write(connect->client, return_msg, strlen(return_msg)) < 0) {
            ....
            puts("Error reading from socket");
            pthread_mutex_lock(&mDataMutex);
            puts("send mutex");
            if(connect->retry == 0)
                connect->retry = 2;
            pthread_mutex_unlock(&mDataMutex);
            puts("send mutex end");

            pthread_mutex_lock(&mDataMutex);
            if(connect->retry == 2) {
                close(connect->client);
                close(connect->s);
                bt_connect(&connect);
                connect->retry = 0;
                puts("send retry success");
            } else
                retry = 1;
            pthread_mutex_unlock(&mDataMutex);

            if(retry == 1)
            {
                puts("bluetooth send retrying in 8 secs");
                sleep(8);
            }
        } else
            retry = 0;

        // clear buffer
        memset(return_msg,0,sizeof return_msg);
        memset(temp,0,sizeof temp);
        // set to send data every second
        sleep(1);
    }

    return 0;
}

void *bt_receive(void *arg)
{
    // similar as above
}

int main(void)
{
    bt_1.retry = 0;
    int rc;
    void *status;
    pthread_t bt_connect_thread, bt_send_thread, bt_receive_thread;
    pthread_attr_t attr;

    /* Initialize and set thread detached attribute */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    // Create BT connect thread and start it
    rc = pthread_create(&bt_connect_thread, &attr, bt_connect, (void *)&bt_1);
    if (rc)
    {
        printf("ERROR; return code from pthread_create() is %d\n", rc);
        return (-1);
    }

    rc = pthread_join(bt_connect_thread, &status);
    rc = pthread_create(&bt_send_thread, &attr, bt_send, (void *)&bt_1);
    rc = pthread_create(&bt_receive_thread, &attr, bt_receive, (void *)&bt_1);

    rc = pthread_join(bt_send_thread, &status);
    rc = pthread_join(bt_receive_thread, &status);
    close(bt_1.client);
    close(bt_1.s);
    pthread_attr_destroy(&attr);

    return 0;
}

代码在发送和接收部分时可能看起来有些混乱,因为我使用互斥锁来检查和调试输出。

这是我得到的输出:

[Bluetooth] Allocating socket... Done!
[Bluetooth] Bind socket... Done!
[Bluetooth] Waiting for incoming connections...
[Bluetooth] Accepted connection from 44:6D:6C:6D:1B:BC
[Bluetooth] Bluetooth connection thread completed
[Bluetooth] Receiving data from device...
rcv mutex in
rcv mutex out
[Bluetooth] Sending data to device...
send mutex in
send mutex out
send mutex in
send mutex out
[Bluetooth-Receive] Error reading from socket
receive mutex
receive mutex end
[Bluetooth-Receive] Connections closed. Reconnecting...
[Bluetooth] Allocating socket... Done!
[Bluetooth] Bind socket... Done!
[Bluetooth] Waiting for incoming connections...
[Bluetooth] Accepted connection from 44:6D:6C:6D:1B:BC
[Bluetooth] Bluetooth connection thread completed
Segmentation fault

我不确定是什么问题,因为我确保在重新打开它之前关闭套接字。有什么帮助/指导吗?谢谢!

编辑:不确定bt_send是否正在阻塞它,因为当我每秒自动发送测试数据时它没有打印出[Bluetooth-Send] Error reading from socket ...(发送和接收都同时运行)

PS。 C和套接字编程新手

1 个答案:

答案 0 :(得分:1)

void *bt_connect(void *arg)
{
    struct BTConnection *connect = (struct BTConnection*)arg;

好的,所以我们需要调用bt_connect向它传递指向BTConnection的指针。

    struct BTConnection *connect = (struct BTConnection*)arg;
...
                bt_connect(&connect);

由于connect是指向BTConnection的指针,&connect是指向指针的指针。那么我们为什么要将它传递给bt_connect