Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ws:// in a C program

Tags:

c

sockets

I have a program that is running as a listener on a socket. From a javascript page I am able to send an open socket request using Websocket (ws://). My issue lies in that I can't seem to see the handshake or reply to it from the C program. I used wireshark to confirm that the javascript is sending the correct handshake but when I try to receive it in the buffer all I get are zeros.

In addition I was able to test the javascript on ws://echo.websocket.org so I am pretty sure it is working correctly. The error I get from the console in my web browser indicates that no reply was received to the handshake.

Edit: I know this is because I don't have a response set up.

My updated C program is as follows

#include <sys/socket.h> //for socket
#include <netinet/in.h>
#include <arpa/inet.h> //inet_addr
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h> //strlen
#include <sys/types.h>

/* main function */
int main() {
    int listenfd = 0, connfd = 0;
    int status;
    struct sockaddr_in serv_addr;
    char revcBuff[1025];
    int dataPresent = 0;
    memset(&serv_addr, 0, sizeof(serv_addr)); //clear the memory for the server_addr
    memset(&revcBuff, 0, sizeof(revcBuff)); //clear the memory for the buffer
    serv_addr.sin_family = AF_INET; //specifiys that the address is IPv4
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//gets the local address
    //serv_addr.sin_port = htons(13669); //gets the local port
    serv_addr.sin_port = htons(5000); //gets the local port

    //designate the socket
    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    if(listenfd < 0) {
        fprintf(stderr, "Socket creation failed due to: %s\n", strerror( errno )); //If the socket creation fails get the error
        return EXIT_FAILURE;
    }

    //binds to the local address and port to listen
    while ( (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))< 0) { 
        fprintf(stderr, "bind failed due to: %s\n Retrying.....\n", strerror( errno )); //If the bind fails get the error
        sleep(3); //time in seconds till next try
    } 

    //listen on socket
    if ( (listen(listenfd, 10))< 0) { 
       fprintf(stderr, "listen failed due to: %s\n", strerror( errno ));//If the listen fails get the error
        return EXIT_FAILURE;
    }

    //main program loop
    fprintf(stderr, "serverSock0-14 now running in listen mode \n");
    while (connfd >= 0) { //while socket is not in error mode try to accept incoming socket requests
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); //wait for an incoming socket request
        if ( connfd == -1) { //if atempted socket request failed 
            fprintf(stderr, "accept failed due to: %s\n", strerror( errno )); // if the accept fails
        }
        fprintf(stdout, "connection opened \n");
        while (dataPresent != -1) { //keep socket open till you receive a packet
            dataPresent = recv(connfd, &revcBuff, sizeof revcBuff, MSG_TRUNC); //receive data from buffer
            //dataPresent = recv(connfd, revcBuff, sizeof revcBuff, MSG_DONTWAIT); //receive data from buffer
            if ( dataPresent == -1) { //test if new data is bad
                fprintf(stderr, "Receive failed due to: %s\n", strerror( errno )); // if the accept fails
            } else if ( dataPresent == 0) { // if the socket is closed on the other end
                break; // Escape to the close socket statement
            } else {
                revcBuff[dataPresent] = '\0'; // null terminate the buffer
                fprintf(stdout, "Buff Hex unsigned: %x %x %x \n", (unsigned int) revcBuff[0], (unsigned int) revcBuff[1], (unsigned int) revcBuff[2]); 
                fprintf(stdout, "Buff Hex: %x %x %x %x %x \n", revcBuff[0], revcBuff[1], revcBuff[2], revcBuff[3], revcBuff[4], revcBuff[5]); 
                fprintf(stdout, "Buff: %s \nbytes received: %i \n", revcBuff, dataPresent); //Print out what you received
            }
            dataPresent = 0;
            usleep(7000);
        }
        if ((close(connfd))==0){//close the socket
            fprintf(stdout, "connection closed\n");
        }
    } //end main program loop
    return EXIT_SUCCESS;
}

Any direction would be super helpful. I am still very new to the world of C.

like image 523
mando222 Avatar asked Apr 28 '26 21:04

mando222


1 Answers

First of all, as pointed out by someone else, you should be using connfd in the recv() call:

recv(connfd, (char*)sendBuff, sizeof sendBuff, MSG_DONTWAIT);

If you have a telnet client available that can connect to your program, you should use that to experiment with your code. For example, if you are running on Linux, start your program in one terminal window and, from another terminal, type

telnet localhost 5000

Here is what happens when I do it:

## The terminal where I run the program (a.out):
$ ./a.out 
connection opened 
Buff:  
connection closed
connection opened 
Buff:  
connection closed

## The terminal window I connect from:

$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

See what's happening? And this is not surprising: the code accepts a connection from the client, tries to read a message from the client without giving it a chance to send it, gets nothing (of course!), doesn't ever send anything back to the client, and closes the connection. Then it waits for the next connection.

Please read some tutorials on C socket programming, play with it, get it to work with a telnet client, and then move on to websockets.

It's a good start, anyway. Good luck!

like image 121
Anatoli P Avatar answered May 01 '26 10:05

Anatoli P