1

这是使用 libwebsocket 1.5 版的客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <signal.h>

#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>

#include <libwebsockets.h>

static volatile int force_exit = 0;
static int state, command_received = 0, forked = 0;

#define MAX_ECHO_PAYLOAD 1400
#define LOCAL_RESOURCE_PATH "./"

struct per_session_data {
	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
	unsigned int len;
};

//for temporary storing data from tcpdump
struct per_session_data data1;

static int callback_echo(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
	struct per_session_data *pss = (struct per_session_data *)user;
	int n;

	switch (reason) {

	/* when the callback is used for client operations --> */

	case LWS_CALLBACK_CLOSED:
	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
		printf("Closed\n");
		state = 0;
		break;
	case LWS_CALLBACK_ESTABLISHED:
	case LWS_CALLBACK_CLIENT_ESTABLISHED:
		printf("Client connected\n");
		state = 2;
		break;

	/* we will receive our packet here*/
	case LWS_CALLBACK_RECEIVE:
	case LWS_CALLBACK_CLIENT_RECEIVE:
		printf("Rx from server: %s\n", (char *)in);
		if (!strcmp((char *)in, "tcpdump"))
		{
			command_received = 1;
		}
		break;

	/* we will send our packet here */
	case LWS_CALLBACK_CLIENT_WRITEABLE:
		printf("client writing to server\n");
		pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);

		n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
		printf("Data: %s\n\n\n\n\n\n\n", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);


		//error handling for write fail and partial writes
		if (n < 0) {
			printf("ERROR %d writing to socket, hanging up\n", n);
			return -1;
		}

		if (n < (int)pss->len) {
			printf("Partial write\n");
			return -1;
		}
		break;

	default:
		printf("default...\n");
		break;
	}

	return 0;
}


/* List of available protocols  */
static struct libwebsocket_protocols protocols[] = {
	{
		"default",		/* name */
		callback_echo,		/* callback */
		sizeof(struct per_session_data)	/* per_session_data_size */
	},
	{
		NULL, NULL, 0		/* End of list */
	}
};

void sighandler(int sig)
{
	force_exit = 1;
}

int main(int argc, char **argv)
{
	//pipe stuff
	int pipe_fd[2];

	if (pipe(pipe_fd) < 0)
	{
		perror("PIPE:");
		exit(-1);
	}

	//for libwebsocket_service
	int n = 0;

	//test port can be overidden
	int port = 9000;
	struct libwebsocket_context *context;
	int opts = 0;

	char interface_name[128] = "";
	const char *interface = NULL;

	int use_ssl = 0;
	char ssl_cert[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
	char ssl_key[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";

	int listen_port = 80;

	struct lws_context_creation_info info;
	char passphrase[256];
	char uri[256] = "/";
	char address[256], ads_port[256 + 30];

	//lws servicing time intervals
	int rate_us = 250000;
	unsigned int oldus = 0;

	struct libwebsocket *wsi;

	//should check this
	int debug_level = 2;

	memset(&info, 0, sizeof info);

	lwsl_notice("Built to support client operations\n");


	//re-configuring server ip and port here
	if (argc == 3)
	{
		strncpy(address, argv[1], sizeof(address) - 1);
		address[sizeof(address) - 1] = '\0';
		port = atoi(argv[2]);
	}
	else if (argc == 1)
	{
		strncpy(address, "localhost", sizeof(address) - 1);
		address[sizeof(address) - 1] = '\0';
		port = 9000;
	}
	else
	{
		printf("Try: ./client.exec <ip> <port>\n");
		exit(-1);
	}

	/* we will only try to log things according to our debug_level */
	setlogmask(LOG_UPTO (LOG_DEBUG));
	openlog("lwsts", 0, LOG_DAEMON);

	/* tell the library what debug level to emit and to send it to syslog */
	lws_set_log_level(debug_level, lwsl_emit_syslog);
	lwsl_notice("libwebsockets echo test - "
			"(C) Copyright 2010-2015 Andy Green <andy@warmcat.com> - "
			"licensed under LGPL2.1\n");

	lwsl_notice("Running in client mode\n");

	listen_port = CONTEXT_PORT_NO_LISTEN;

	lwsl_info("requiring server cert validation againts %s\n", ssl_cert);
	info.ssl_ca_filepath = ssl_cert;

	info.port = listen_port;
	info.iface = interface;
	info.protocols = protocols;

#ifndef LWS_NO_EXTENSIONS
	info.extensions = libwebsocket_get_internal_extensions();
#endif

	info.gid = -1;
	info.uid = -1;
	info.options = opts;

	context = libwebsocket_create_context(&info);
	if (context == NULL) {
		lwsl_err("libwebsocket init failed\n");
		return -1;
	}



	signal(SIGINT, sighandler);

	n = 0;

	while (n >= 0 && !force_exit) 
	{
		//do connect only once
		if (!state) {
			state = 1;
			printf("Client connecting to %s:%u....\n", address, port);

			address[sizeof(address) - 1] = '\0';
			sprintf(ads_port, "%s:%u", address, port & 65535);

			wsi = libwebsocket_client_connect(context, address, port, use_ssl, uri, ads_port, ads_port, NULL, -1);
			if (!wsi) {
				printf("Client failed to connect to %s:%u\n", address, port);
				goto bail;
			}
		}


		if (command_received == 1 && !forked)
		{
			printf("Going to fork\n");
			forked = 1;
			pid_t child_pid = fork();

			if (child_pid == -1)
			{
				perror("FORK:");
				exit(-1);
			}

			else if (child_pid == 0)
			{
				close(pipe_fd[0]);
				printf("Starting tcpdump\n");

				if (dup2(pipe_fd[1], 1) < 0)
				{
					perror("DUP2:");
					exit(-1);
				}
				
				//closing the connection to server for child
				libwebsocket_context_destroy(context);
				closelog();

				char *cmd[] = {"tcpdump", "-i", "any", NULL};

				if (execv("/usr/sbin/tcpdump", cmd) < 0)
				{
					perror("EXECV:");
					exit(-1);
				}
			}
		}
		
	/*	if (forked == 1)
		{
			close(pipe_fd[1]);
		}
*/
		if (command_received == 1)
		{
			//stay here if the pipe is empty else try to read max 1400 bytes of data
			while ((data1.len  = read(pipe_fd[0], data1.buf + LWS_SEND_BUFFER_PRE_PADDING, 1400)) <= 0);
			//check if server wants any service

			//printf("%s\n\n\n\n\n\n\n", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
			libwebsocket_callback_on_writable(context, wsi);
		}

		//This fn times out every 10usec
		n = libwebsocket_service(context, 10);

	}

	//bail: jump from while loop also if connect fails
bail:
	libwebsocket_context_destroy(context);

	printf("libwebsockets-test-echo exited cleanly\n");
	closelog();

	return 0;
}

这是我使用 socket.io 的服务器代码

var io = require('socket.io')();
var middleware = require('socketio-wildcard')();

io.use(middleware);

io.on('connection', function(socket) {
  console.log('On socket connection')
  socket.on('*', function(event, data){
    console.log("---- Event ----- : " + JSON.stringify(event));
    console.log("---- Data ----- : " + JSON.stringify(data))
  });
});

io.listen(9000, 'localhost');

客户端无法与服务器连接。当我用 strace 测试客户端时,它会无限接收如下

recv(8, "", 1, 0)                       = 0
recv(8, "", 1, 0)                       = 0
recv(8, "", 1, 0)                       = 0
.
.
.
.

请指出我的错误。任何帮助表示赞赏。

谢谢

4

0 回答 0