aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2009-11-12 22:16:52 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2009-11-12 22:16:52 +0000
commit7aedde85960b3578fff3c8cce7af5bf1c9f81b3b (patch)
treeccc8d9513c5f545e68c08535e76c2b09821efbf2
parentf704b10df41306acbccaa092fa2da05e2ca51d51 (diff)
Using pthreads to send each message to each client in its own thread. This should eliminate hangups when clients disappear halfway through, and increase responsiveness of Pd with [tcpserver]. Messages are sent as one unit instead of byte-by-byte. Select() is no longer used to check for available space in the buffer.
svn path=/trunk/externals/mrpeach/; revision=12760
-rw-r--r--net/tcpserver.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/net/tcpserver.c b/net/tcpserver.c
index 7dcaa8c..541ee11 100644
--- a/net/tcpserver.c
+++ b/net/tcpserver.c
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <stdio.h>
+#include <pthread.h>
#if defined(UNIX) || defined(unix)
#include <sys/socket.h>
#include <netinet/in.h>
@@ -75,6 +76,15 @@ typedef struct _tcpserver_socketreceiver
t_tcpserver_socketreceivefn sr_socketreceivefn;
} t_tcpserver_socketreceiver;
+typedef struct _tcpserver_send_params
+{
+ int client;
+ int sockfd;
+ char *byte_buf;
+ size_t length;
+ t_int timeout_us;
+} t_tcpserver_send_params;
+
typedef struct _tcpserver
{
t_object x_obj;
@@ -105,6 +115,7 @@ static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd)
static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x);
static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv);
static void tcpserver_send_bytes(int sockfd, t_tcpserver *x, int argc, t_atom *argv);
+static void *tcpserver_send_buf_thread(void *arg);
static size_t tcpserver_send_buf(int client, int sockfd, char *byte_buf, size_t length, t_int timeout_us);
static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv);
static void tcpserver_output_client_state(t_tcpserver *x, int client);
@@ -304,16 +315,19 @@ static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x)
static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *argv)
{
- static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size
- int i, j, d;
- unsigned char c;
- float f, e;
- int length;
- size_t flen = 0;
- int sockfd = x->x_fd[client];
- char fpath[FILENAME_MAX];
- FILE *fptr;
- t_atom output_atom[3];
+ static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size
+ int i, j, d;
+ unsigned char c;
+ float f, e;
+ int length;
+ size_t flen = 0;
+ int sockfd = x->x_fd[client];
+ char fpath[FILENAME_MAX];
+ FILE *fptr;
+ t_atom output_atom[3];
+ t_tcpserver_send_params *ttsp;
+ pthread_t sender_thread;
+ int sender_thread_result;
/* process & send data */
if(sockfd >= 0)
@@ -387,6 +401,18 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a
length = j;
if (length > 0)
{
+ ttsp = (t_tcpserver_send_params *)getbytes(sizeof(t_tcpserver_send_params));
+ if (ttsp == NULL)
+ {
+ error("%s: unable to allocate %d bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params));
+ return;
+ }
+ ttsp->client = client;
+ ttsp->sockfd = sockfd;
+ ttsp->byte_buf = byte_buf;
+ ttsp->length = length;
+ ttsp->timeout_us = x->x_timeout_us;
+ sender_thread_result = pthread_create(&sender_thread, NULL, tcpserver_send_buf_thread, (void *)ttsp);
flen += tcpserver_send_buf(client, sockfd, byte_buf, length, x->x_timeout_us);
}
}
@@ -397,11 +423,27 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a
outlet_anything( x->x_status_outlet, gensym("sent"), 3, output_atom);
}
+// send a buffer in its own thread
+static void *tcpserver_send_buf_thread(void *arg)
+{
+ t_tcpserver_send_params *ttsp = (t_tcpserver_send_params *)arg;
+ int result;
+
+ result = send(ttsp->sockfd, ttsp->byte_buf, ttsp->length, 0);
+ if (result <= 0)
+ {
+ sys_sockerror("tcpserver: send");
+ post("%s_send_buf: could not send data to client %d", objName, ttsp->client+1);
+ }
+ freebytes (arg, sizeof (t_tcpserver_send_params));
+ return NULL;
+}
+
+// send a buffer one byte at a time, no thread
static size_t tcpserver_send_buf(int client, int sockfd, char *byte_buf, size_t length, t_int timeout_us)
{
char *bp;
size_t sent = 0;
- double timebefore;
int result;
fd_set wfds;
struct timeval timeout;