Websocket connection keeps prematurely closing the connection - c

So, I am trying to build a C application which functions as a Websockets Server.There are many related questions on here, but none of them seem to be able to help with the problem. The program is able to initially establish a connection, complete the handshake for the websocket successfully, however, cannot seem to be able to keep the connection open. On the client side, I get the error
WebSocket.js:7605 Uncaught Error: Attempt to send message on unopened or closed WebSocket
at _8b2.window.WebSocket._8d2.send (WebSocket.js:7605)
at (index):34
whenever I try to use the send() function on the websocket connection on the client side. And also it gives me the error
WebSocket connection to 'ws://127.0.0.1:5959/?.kl=Y' failed: WebSocket is closed before the connection is established.
Here is the source code of the server:
int new_socket;
int activity;
int i;
int sd;
int max_sd;
int bytes_read;
fd_set readfds;
int master_socket;
noPollConn* new_conn;
/*Create no poll context*/
noPollCtx* ctx = nopoll_ctx_new();
noPollConn* conn;
char buffer[3000];
/*Create a connection listener at 127.0.0.1 (loopback) on port 5959*/
noPollConn * listener = nopoll_listener_new(ctx, "127.0.0.1","5959");
/*Get the socket of the lister*/
master_socket = nopoll_conn_socket(listener);
if(!nopoll_conn_is_ok(listener)) {
perror("There was an error creating the listener!\n");
exit(EXIT_FAILURE);
}
puts("Waiting for connections ...");
while(TRUE){
printf("Start of the while loop\n");
FD_ZERO(&readfds);
FD_SET(master_socket, &readfds);
max_sd = master_socket;
printf("The number of connections is %i\n",cons);
for (i = 0 ; i < cons ; i++) {
sd = nopoll_conn_socket((noPollConn*)vector_get(clients,i));
if(sd > 0)
FD_SET(sd,&readfds);
if(sd > max_sd)
max_sd = sd;
}
printf("The max fd is %i\n",max_sd);
activity = select(max_sd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR)) {
puts("select error");
exit(EXIT_FAILURE);
}
if (FD_ISSET(master_socket, &readfds)){
new_conn = nopoll_conn_accept(ctx,listener);
puts("Waiting for the connection to be ready");
nopoll_conn_is_ready(conn);
/*Vector is actually a doubly linked list*/
vector_push(&clients,new_conn);
cons++;
}
/*TODO: Implement disconnect*/
for (i = 0; i < cons; i++){
printf("Checking on user %i\n",i);
conn = (noPollConn*)vector_get(clients,i);
sd = nopoll_conn_socket(conn);
if (FD_ISSET(sd, &readfds)){
printf("Receiving info from socket no. %d...\n",sd);
bytes_read = recv(sd,buffer,4000,MSG_DONTWAIT);
buffer[bytes_read] = '\0';
printf("Received the msg --> %s\n",buffer);
}
}
memset(buffer,0,3000);
}
Just a warning though, this code does go in an infinite loop right now as I have not implemented disconnection from the client on the server side.
For the client
<pre><code>
var connection = new WebSocket('ws://127.0.0.1:5959');
connection.onopen = function(){
connection.send("TEST");
alert("Connected");
}
connection.onerror = function(error){
console.log('Error detected: ' + error);
}
connection.onmessage = function (event) {
alert(event.data);
}
connection.close();
</code></pre>
Perhaps I am missing something very important? I have gone through many tutorials, and I can't seem to figure out what the issue is. Any help is greatly appreciated!
Calling .send() in the .onopen() function results in the error:
WebSocket connection to 'ws://127.0.0.1:5959/?.kl=Y' failed: WebSocket is closed before the connection is established.
UPDATE
The error is on the server side. It might be related to me handling the connection as though it were a socket in some regards in the C code.

If no errors are logged at server, the issue could be call to .send() before open event occurs. Call .send() within open event handler. Else, the issue is at server.
const socket = new WebSocket("ws://echo.websocket.org/");
socket.onopen = function(e) {
socket.send("WebSocket rocks");
console.log("self.socket event.type:", e.type);
};
socket.onmessage = function(e) {
console.log(e.data);
};
socket.onerror = function(e) {
console.log("self.socket error", e);
};
socket.onclose = function(e) {
console.log("self.socket event.type", e.type);
};
See How do I test my WebSocket which is developed in JavaScript
plnkr http://plnkr.co/edit/W8Wgyw0mbxdMkMMe4wg4?p=preview

Related

Chat room using socket programming with select() - winsock - C

I try to create a server-client application where the server provides a chat service to all clients that connect to the server. The server and client use cryptographic algorithms and protocols to secure data transmitted over the network. I can't figure out why the chat code isn't working properly.
I use the select() function to operate multiple drawers at the same time. If I use only a piece of code when multiple clients connect to the server and send data to the server and it gets everything, that's fine, but as soon as I try to write a piece of code that would be a chat function, even if multiple clients connect, the server serves only the last connected client. I use a link dynamic list to store the necessary client information, and when I can list currently connected clients, if I don't use part of the chat room code, all clients I connect will be accepted, and as soon as I use the chat room code part, only the last connected client.
This is code for server:
while(1) {
fd_set reads;
reads = master;
//The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O
if (select(max_socket+1, &reads, 0, 0, 0) < 0) {
fprintf(stderr, "select() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
SOCKET i;
//Loop through each possible socket
for(i = 1; i <= max_socket; ++i) {
if (FD_ISSET(i, &reads)) {
//If socket_listen, create TCP connection of accept() function
if (i == socket_listen) {
//
client_info = create_client();
client_info->client_len = sizeof(client_info->client_address);
client_info->sock_fd = accept(socket_listen,
(struct sockaddr*) &client_info->client_address,
&client_info->client_len);
if (!ISVALIDSOCKET(client_info->sock_fd)) {
fprintf(stderr, "accept() failed. (%d)\n",
GETSOCKETERRNO());
return 1;
}
FD_SET(client_info->sock_fd, &master);
if (client_info->sock_fd > max_socket)
max_socket = client_info->sock_fd;
//Prints the client address using the getnameinfo() function
getnameinfo((struct sockaddr*)&client_info->client_address,
client_info->client_len,
client_info->address_buffer,
100, 0, 0,
NI_NUMERICHOST);
printf("New connection %s\n", client_info->address_buffer);
printf("\nWaiting for succeses Salt handshake...\n");
//Salt handshake
salt_hndshk(client_info);
//Insert client to the list of clients
insert(p_list, client_info);
//List of clients connected to the server with a successful Salt handshake
listing_clients(p_list);
} else {
memset(rx_buffer, 0, sizeof(hndsk_buffer));
//Search for clients by sockets and the is in the list
//the server decrypts the data from the client
CLIENT *client_decrypt = create_client();
client_decrypt = search_client(p_list, i);
ret_msg = salt_read_begin_pom(&client_decrypt->channel, rx_buffer,
sizeof(rx_buffer), &msg_in, pom_buffer, &decrypt_size);
//Check if SALT_ERROR from message
if(ret_msg == SALT_ERROR) {
printf("\tThe client disconnects from the server.\n");
printf("\tThe server has closed him socket\n");
realese_client(p_list, client_decrypt);
FD_CLR(i, &master);
CLOSESOCKET(i);
continue;
}
//Freeing client memory
free(client_decrypt);
}
//Chat room service
SOCKET j;
for(j = 1; j <= max_socket; ++j){
if(FD_ISSET(j, &master)){
if (j == socket_listen || j == i){
continue;
} else {
memset(rx_buffer, 0, sizeof(hndsk_buffer));
//Search for clients by sockets and the is in the list
CLIENT *client_encrypt = create_client();
client_encrypt = search_client(p_list, j);
//Prepare data before send
salt_write_begin(tx_buffer, sizeof(tx_buffer), &msg_out);
//Copy clear text message to be encrypted to next encrypted package
salt_write_next(&msg_out, (uint8_t * )pom_buffer, decrypt_size);
//Wrapping, creating encrpted messages
salt_write_execute(&client_encrypt->channel, &msg_out, false);
//Freeing client memory
free(client_encrypt);
}
} //if(FD_ISSET(j, &master)
} //for(j = 1; j <= max_socket; ++j)
//Finish chat room service
} //if FD_ISSET
} //for i to max_socket
}
There is a link to the application on this link:
tcp_salt
You have logic errors in both of your inner for loops.
When reading from/writing to a non-listening client socket, DO NOT call create_client() at all, you are creating memory leaks with it:
CLIENT *client_decrypt = create_client();
client_decrypt = search_client(...); // <-- LEAK!
CLIENT *client_encrypt = create_client();
client_encrypt = search_client(...); // <-- LEAK!
Call create_client() ONLY when you accept() a new client. And DO NOT call free() on any CLIENT you read from/write to. Call that ONLY when you are removing a CLIENT from p_list.
You are corrupting your p_list on each loop iteration, leaving it with a bunch of dangling pointers to invalid CLIENTs.
Also, your writing code is not checking for errors to disconnect and remove dead clients.
Try something more like this:
while(1) {
fd_set reads;
reads = master;
//The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O
if (select(max_socket+1, &reads, 0, 0, 0) < 0) {
fprintf(stderr, "select() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
//Loop through each possible socket
for(SOCKET i = 1; i <= max_socket; ++i) {
if (!FD_ISSET(i, &master)) {
continue;
}
if (FD_ISSET(i, &reads)) {
//If socket_listen, create TCP connection of accept() function
if (i == socket_listen) {
//
CLIENT *client_info = create_client();
client_info->client_len = sizeof(client_info->client_address);
client_info->sock_fd = accept(socket_listen,
(struct sockaddr*) &client_info->client_address,
&client_info->client_len);
if (!ISVALIDSOCKET(client_info->sock_fd)) {
fprintf(stderr, "accept() failed. (%d)\n",
GETSOCKETERRNO());
return 1;
}
FD_SET(client_info->sock_fd, &master);
if (client_info->sock_fd > max_socket)
max_socket = client_info->sock_fd;
//Prints the client address using the getnameinfo() function
getnameinfo((struct sockaddr*)&client_info->client_address,
client_info->client_len,
client_info->address_buffer,
100, 0, 0,
NI_NUMERICHOST);
printf("New connection %s\n", client_info->address_buffer);
printf("\nWaiting for succesful Salt handshake...\n");
//Salt handshake
salt_hndshk(client_info);
//Insert client to the list of clients
insert(p_list, client_info);
//List of clients connected to the server with a successful Salt handshake
listing_clients(p_list);
continue;
}
memset(rx_buffer, 0, sizeof(rx_buffer));
//Search for clients by sockets and the is in the list
//the server decrypts the data from the client
CLIENT *client_decrypt = search_client(p_list, i);
ret_msg = salt_read_begin_pom(&client_decrypt->channel, rx_buffer,
sizeof(rx_buffer), &msg_in, pom_buffer, &decrypt_size);
//Check if SALT_ERROR from message
if (ret_msg == SALT_ERROR) {
printf("\tThe client disconnects from the server.\n");
printf("\tThe server has closed his socket\n");
release_client(p_list, client_decrypt);
free(client_decrypt);
CLOSESOCKET(i);
FD_CLR(i, &master);
continue;
}
//Chat room service
for(SOCKET j = 1; j <= max_socket; ++j){
if (!FD_ISSET(j, &master) || j == socket_listen || j == i){
continue;
}
memset(rx_buffer, 0, sizeof(rx_buffer));
//Search for clients by sockets and the is in the list
CLIENT *client_encrypt = search_client(p_list, j);
//Prepare data before send
ret_msg = salt_write_begin(tx_buffer, sizeof(tx_buffer), &msg_out);
//Copy clear text message to be encrypted to next encrypted package
if (ret_msg != SALT_ERROR)
ret_msg = salt_write_next(&msg_out, (uint8_t * )pom_buffer, decrypt_size);
//Wrapping, creating encrpted messages
if (ret_msg != SALT_ERROR
ret_msg = salt_write_execute(&client_encrypt->channel, &msg_out, false);
//Check if SALT_ERROR from message
if (ret_msg == SALT_ERROR) {
printf("\tThe client disconnects from the server.\n");
printf("\tThe server has closed his socket\n");
release_client(p_list, client_decrypt);
free(client_decrypt);
CLOSESOCKET(i);
FD_CLR(i, &master);
continue;
}
}
}
}
}

inter-process communication between linux and dotnet using mkfifo

We have an application written in c that sends events/notifications to an application written in c#. Both applications run on the same linux computer.
The C application:
The C application is Asterisk and we modified the source code (it is open source) so that it can send events to our dotnet console application. The way we currently send events is simply by appending text to a file. For example this is how we send an event that a new peer (ip-phone) connected:
// place this on chan_sip.c
// Example: 1-LN-48T6-E3C5-OFWT|10.0.0.103:5868|189.217.18.244|10216|Z 3.9.32144 r32121
if(!ast_sockaddr_isnull(&peer->addr))
{
// lock
ast_mutex_lock(&some_lock);
// write to file
FILE *pFile;
pFile=fopen("/var/log/asterisk/peer-subscriptions.txt", "a");
if(pFile==NULL) { perror("Error opening file."); }
else {
fprintf(pFile,"%s|%s|%s|%s|%s\n",
/* 1-LN-48T6-E3C5-OFWT */ peer->name,
/* 10.0.0.103:5868 */ pvt->initviasentby,
/* 189.217.18.244 */ ast_sockaddr_stringify_addr(&peer->addr),
/* 10216 */ ast_strdupa(ast_sockaddr_stringify_port(&peer->addr)),
/* Z 3.9.32144 */ peer->useragent
// Other:
// peer->fullcontact, // sip:1-LN-48T6-E3C5-OFWT#189.217.18.244:10216;rinstance=8b4135488f735cbf;transport=UDP
// pvt->via // SIP/2.0/UDP 54.81.92.135:20001;branch=z9hG4bK58525e18;rport
);
}
fclose(pFile);
// unlock
ast_mutex_lock(&some_lock);
}
The C# application
The c# application is a console application that opens that file for reading events nothing fancy.
So basically the C application is writing to a text file and the c# application is reading from that text file.
Question
Over time the file gets to large and I do not want to get in the trouble of truncating it and creating another lock meanwhile it truncates etc... making use of mkfifo seems to be exactly what I want. Since I am relatively new to linux I want to make sure I understand how it works before using it. I know the basics of C (I am no expert) and will like to use a more efficient approach. Do you guys recommend using mkfifo, namedpipes or tcp?
Example 1:
mkfifo works amazing with few lines but when I try to read a lot of lines it fails. Take this example:
mkfifo foo.pipe # create a file of type pipe
On terminal one write to that file
echo "hello world" >> foo.pipe # writes hello world AND blocks until someone READS from it
On a separate terminal I do:
cat foo.pipe # it will output hello world. This will block too until someone WRITES to that file
Example 2:
mkfifo foo.pipe # create a file of type pipe. If it exists already do not create again
On terminal 1 read from that file
tail -f foo.pipe # similar to cat foo.pipe but it keeps reading
On Terminal 2 write to that file but a lot of data
echo ~/.bashrc >> foo.pipe # write the content of file ~/.bashrc to that file
This does not work and only a few lines of that file are displayed on the console. How can I make proper use of mkfifo in order to read all text? Should I use a different approach and use tcp instead?
I would use an AF_UNIX socket connection.
I just ended using tcp. I am sending 10,000 short messages in 10 seconds with no problem.
C code (client)
#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>
int send_data(void)
{
int socket_desc;
struct sockaddr_in server;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket \n");
return 1;
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 11234 );
//Connect to remote server
if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
{
printf("connect error \n");
close(socket_desc);
return 2;
}
char *message;
message = "hello world";
if( send(socket_desc , message , strlen(message) , 0) < 0)
{
printf("Send failed \n");
close(socket_desc);
return 3;
}
close(socket_desc);
return 0;
}
int main(int argc , char *argv[])
{
// send 1000 messages
for(int i=0; i<1000; i++)
{
send_data();
// 10 milliseconds
usleep(10000);
}
return 0;
}
C# code (server)
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Ipc_Tcp
{
// Thread signal.
public static ManualResetEvent _semaphore = new ManualResetEvent(false);
// maximum length of the pending connections queue.
const int _max_length_pending_connections_queue = 50;
const ushort _port = 11234;
static int _counter = 0;
public static void StartListening()
{
IPEndPoint localEndPoint = new IPEndPoint(System.Net.IPAddress.Loopback, _port);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(_max_length_pending_connections_queue);
Console.WriteLine("Waiting for a connection...");
while (true)
{
// Set the event to nonsignaled state.
_semaphore.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
_semaphore.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine("Something bad happened:");
Console.WriteLine(e.ToString());
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
}
// On new connection
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
_semaphore.Set();
var cntr = Interlocked.Increment(ref _counter);
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket socket = listener.EndAccept(ar);
var data = new byte[1024];
var i = socket.Receive(data);
// print message every 100 times
if (cntr % 100 == 0)
Console.WriteLine($"[{cntr}] Received data: {System.Text.Encoding.UTF8.GetString(data, 0, i)}");
// close socket we are only receiving events
socket.Close();
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
As #resiliware stated it is probably best to use a unix socket.
This example shows how to communicate between C and C# using a unix socket:
Client (written in C running on ubuntu)
#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<unistd.h>
int send_data(void)
{
int sock;
int conn;
struct sockaddr saddr = {AF_UNIX, "/tmp/foo.sock"};
socklen_t saddrlen = sizeof(struct sockaddr) + 6;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
conn = connect(sock, &saddr, saddrlen);
char BUFF[1024];
char *message;
message = "hello world";
if( send(sock , message , strlen(message) , 0) < 0)
{
printf("Send failed \n");
close(sock);
return 3;
}
// I am not sure if I should close both or only the socket.
close(conn);
close(sock);
return 0;
}
int main(int argc , char *argv[])
{
// send 5000 messages
for(int i=0; i<4000; i++)
{
send_data();
// sleep 1 millisecond
usleep(1000);
}
return 0;
}
Server (written in C# running on same ubuntu machine)
using System;
using System.Net.Sockets;
using System.Threading;
class Program
{
// unix Endpoint that we will use
const string path = "/tmp/foo.sock";
// Thread signal.
public static ManualResetEvent _semaphore = new ManualResetEvent(false);
// maximum length of the pending connections queue.
const int _max_length_pending_connections_queue = 100;
// Counts the number of messages received
static int _counter = 0;
public static void StartListening()
{
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
// create unix socket
var listener = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
try
{
// listener.Bind(localEndPoint);
listener.Bind(new UnixDomainSocketEndPoint(path));
listener.Listen(_max_length_pending_connections_queue);
Console.WriteLine("Waiting for a connection...");
// keep listening for connections
while (true)
{
// Set the event to nonsignaled state.
_semaphore.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
_semaphore.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine("Something bad happened:");
Console.WriteLine(e.ToString());
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
}
// On new connection
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
_semaphore.Set();
var cntr = Interlocked.Increment(ref _counter);
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket socket = listener.EndAccept(ar);
var data = new byte[1024];
var i = socket.Receive(data);
// print message every 100 times
//if (cntr % 100 == 0)
Console.WriteLine($"[{cntr}] Received data: {System.Text.Encoding.UTF8.GetString(data, 0, i)}");
// close socket we are only receiving events
socket.Close();
}
static void Main(string[] args)
{
StartListening();
}
}
Client (If you will like the code of the client to be written on C# instead of C)
using (var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))
{
socket.Connect(new UnixDomainSocketEndPoint(path));
// send hello world
var dataToSend = System.Text.Encoding.UTF8.GetBytes("Hello-world!");
socket.Send(dataToSend);
}

ePoll not accepting some clients

I have implemented a server using epoll, in what I believe to be the standard way, in fact, when I implemented it using the example from the epoll man page I got the same behavior.
This leads me to believe that there must be a problem with my client, and that I'm making assumptions somehow where I shouldn't. The main method of my client forks n number of clients, which then connect to the server. What I'm seeing is that usually a subset of these clients don't trigger the epoll, and never hit the
accept() call. The three-way-handshake completes because there is a listening socket, so the client behaves as if it where accepted, but it never gets served, as the server doesn't know about it. I can't figure out why this is happening, and haven't been able to find similar questions online. Thoughts?
Here's the relevant server code:
// wrapper which binds to port and exits on error
listenFD = tcpSocket(host, port);
SetNonblocking(listenFD);
// wrapper which listens and exits on error
tcpListen(listenFD);
epollFD = epoll_create(EPOLL_QUEUE_LEN);
if (epollFD == -1)
errSystem("epoll_create");
// Add the server socket to the epoll event loop
event.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET;
event.data.fd = listenFD;
if (epoll_ctl (epollFD, EPOLL_CTL_ADD, listenFD, &event) == -1)
errSystem("epoll_ctl");
while(TRUE){
//struct epoll_event events[MAX_EVENTS];
numFDs = epoll_wait(epollFD, events, EPOLL_QUEUE_LEN, -1);
for (i = 0; i < numFDs; i++){
// Case 1: Error condition
if (events[i].events & (EPOLLHUP | EPOLLERR)){
errMessage("epoll: EPOLLERR");
Close(events[i].data.fd);
printf("Closed connection to %d\n", events[i].data.fd);
fflush(stdout);
continue;
}
// Case 2: Server is receiving a connection request
if (events[i].data.fd == listenFD){
// socketlen_t
clientLen = sizeof(client);
newFD = Accept (listenFD, (SA *)&client, &clientLen);
SetNonblocking(newFD);
// Set receive low water mark to message size
SetSockOpt(newFD, SOL_SOCKET, SO_RCVLOWAT, &lowWater, sizeof(lowWater));
// Add the new socket descriptor to the epoll loop
event.data.fd = newFD;
event.events = EPOLLIN | EPOLLET;
if (epoll_ctl (epollFD, EPOLL_CTL_ADD, newFD, &event) == -1)
errSystem ("epoll_ctl");
printf("Connected to client on socket %d\n", newFD);
// tell the client we're connected and ready
// (this is an attempt to fix my issue. I'd rather not do this...)
Writen(newFD, buffer, CLIENT_MESSAGE_SIZE);
continue;
}
if (events[i].events & EPOLLIN){
//serve the client
}
}
}
And this is the client code. One instance of these works, but if I fork more than 5 or so (sometimes just 2) a number of them won't get accepted.
int Client(const char *host, const int port, const int timeLen, const int clientNum){
long double delta;
PTSTRUCTS ptstructs = (PTSTRUCTS) malloc(sizeof(TSTRUCTS));
size_t result;
stop = FALSE;
cNum = clientNum;
Signal(SIGINT, closeFD);
Signal(SIGALRM, sendMessage);
nsockets = 0;
// wrapper which calls connect() and exits with message on error
connectFD = tcpConnect(host, port);
printf("%d connected to server:\n", clientNum);
fflush(stdout);
bzero(sbuf, CLIENT_MESSAGE_SIZE);
// initialize client message
strcpy(sbuf, CLIENT_MESSAGE);
// get the start time
getStartTime(ptstructs);
getEndTime(ptstructs);
while((delta = getTimeDelta(ptstructs)) < timeLen){
// One or more clients blocks here for ever
if ((result = receiveMessage()) < CLIENT_MESSAGE_SIZE){
break;
}
//sendMessage();
alarm(1);
//delay(USER_DELAY);
getEndTime(ptstructs);
}
stop = TRUE;
Close (connectFD);
getEndTime(ptstructs);
delta = getTimeDelta(ptstructs);
printf("Client %d served %ld bytes in %.6Lf seconds.\n", clientNum, byteCount, delta);
fflush(stdout);
// free heap memory
free(ptstructs);
return (1);
}
I should probably note that I'm seeing the same behavior if I don't set EPOLLET. I originally thought this might be the result of edge-triggering behavior, but nope.
Does your backlog argument of listen() greater than the number of clients?
#some-programmer-dude, sorry for not commentting, the closed fd will be removed from epoll event set automatically http://man7.org/linux/man-pages/man7/epoll.7.html

Chrome closes TCP connection after response

I have this code that handles some very basic http requests. I want it to support persistent connections. If I request some pages through firefox the session/connection is reused as indended. Chrome, however, closes the connection after each request/response independent of whether the Connection: keep-alive header is included or not.
Is this intended or is my read/write loop wrong?
#include<sys/socket.h>
// some setup code
listen(sockfd, 5);
// accept new connections
while (true) {
int session_sock_fd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if (newsockfd < 0) {
// error
} else {
// create session
}
// session main loop, each session runs in its own thread
while(true) {
int n = read(session_sock_fd, buffer, buffer_size);
if (n < 0) {
// connection time out or some error
break;
} else if (n == 0) {
break; // client has closed the conneciton
}
// parse the request
// send response
char* resp_data = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\n"
"Content-Length: xxx\r\nDate: some date\r\n\r\n"
"response_body\r\n";
n = write(session_sock_fd, resp_data, size);
if (n < 0) {
// error, unable to write to socket
break;
}
}
It seems my problem was that I didn't include the final "\r\n" when I calculated content-length. It seems to be working now!

how to run the timer task in parallel with socket receive data?

void main()
{
HANDLE h1,h2,h3;
uint8 data;
double Task2ms_Raster, Task10ms_Raster, Task100ms_Raster ;
CreateSocket();
XCP_FN_TYPE Xcp_Initialize( );
while(1)
{
data = recv(fd, recv_data, 99, 0);
if (data == SOCKET_ERROR) {
printf("recv failed with error %d\n", WSAGetLastError());
}
else
{
pChunkData = &recv_data;
chunkLen = sizeof(pChunkData);
XcpIp_RxCallback ((uint16) chunkLen, (char*) pChunkData, (uint16) port);
}
}
h1=TimerTask(2,TASK1,&Task2ms_Raster);
h2=TimerTask(10,TASK2,&Task10ms_Raster);
h3=TimerTask(100,TASK3,&Task100ms_Raster);
XCP_FN_TYPE XcpIp_OnTcpCxnClosed( port );
}
I have created the server socket and recieving data from the client via the ip address and the port number. I have to run the timer task in parallel with the recieve data from the socket.The function definition of create scoket and TimerTask functionality is not shown. So could anyone please help me how to run the timer task parallel to it ??

Resources