Re: GIO - Simple socket Client - Need suggestions on which API set to use (or sample code)



Well I think from the archives I saw mention of GIOChannel, so gave it a try.

        case CONNECT:
            sock = socket_connect(host, 4321);
            if (sock < 0) {
                fcm->State = OFFLINE;
                break;
            }
            fcm->iochannel =  g_io_channel_unix_new (sock);
            g_io_channel_set_encoding(fcm->iochannel, NULL, &error);
            g_io_channel_set_buffered(fcm->iochannel, FALSE);
            fcm->State = CONNECTED;
fcm->sid = g_io_add_watch(fcm->iochannel, (G_IO_IN | G_IO_ERR | G_IO_HUP), fibs_callback, (gpointer)fcm);
            break;
        case BOT_CON_ERROR:
            g_io_channel_unref(fcm->iochannel);
            g_io_channel_shutdown(fcm->iochannel, FALSE, NULL);
            fcm->iochannel = NULL;
            break;

and my callback is:

gboolean fibs_callback( GIOChannel *ioch, GIOCondition condition, gpointer data)
{
    FCM *fcm = (FCM *)data;
    char message[MAXBUF];
    gsize l, len, need;
    GIOStatus status;
    GError *error=NULL;

    printf("callback: %d\r\n", condition);fflush(stdout);
    // (G_IO_IN | G_IO_ERR | G_IO_HUP)
    if ((condition & G_IO_HUP) || (condition & G_IO_ERR)) {
        fcm->State = CON_ERROR;
        return FALSE;
    }
    if (condition & G_IO_IN) {
        // Received Data
        len = strlen(fcm->buffer);
        need = MAXBUF - len;
//printf("reading: len %d need %d buff: %s\r\n", len, need, fcm->buffer);fflush(stdout); status = g_io_channel_read_chars(fcm->iochannel, fcm->buffer+len, need, &l, &error);
        if (status != G_IO_STATUS_NORMAL) {
            printf("Bad Read Errno %d\n", (int)status);fflush(stdout);
            fcm->State = CON_ERROR;
            return 0;
        } /* Process data */
        //printf("read %d buff is: %s\r\n", l, fcm->buffer);fflush(stdout);
[snip]
        }
    }
    return TRUE;
}

I did find that I needed to turn off buffering with g_io_channel_set_buffered(fcm->iochannel, FALSE);

Maybe because not all my data is complete lines (like a login prompt)

I hope this helps someone.

Tom

ps. here is my socket_connect function, pretty standard code

int socket_connect(char *host, int port)
{
    struct sockaddr_in serv_addr;
    static struct hostent *server;
    static char last_host[256];
    int servfd;
    char **p;

    if(last_host[0] || strcasecmp(last_host, host)!=0) {
        if(!(server = gethostbyname(host))) {
            printf("failed to look up server (%s)\n%d: %strerrors",
                host, h_errno, strerror(h_errno));
            return -1;
        }
        strncpy(last_host, host, 255);
    }
    if((servfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Socket create error (%d): %s", errno, strerror(errno));
        return -1;
    }

    printf("connecting to %s:%d", host, port);

    for (p = server->h_addr_list; *p; p++) {
        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        memcpy(&serv_addr.sin_addr.s_addr, *p, server->h_length);
        serv_addr.sin_port = htons(port);

        printf("trying %s", inet_ntoa(serv_addr.sin_addr));
if(connect(servfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) { if(errno!=ECONNREFUSED && errno!=ETIMEDOUT && errno!=ENETUNREACH) {
                break;
            }
        } else {
            printf("connected\n");
            return servfd;
        }
    }

printf("Could not connect to %s:%d\n%d:%s", host, port, errno, strerror(errno));
    close(servfd);
    return -1;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]