LINUX.ORG.RU

NetCat... надо написать сервер и клиент


0

0

Есть сервак под Линукс собирающий инфу с девайсов. Вот захотели купить девайсы в другой фирмы у них сервера под Линукс нет...

Девайсы передают данные в текстовых форматах. Хочу написать сервер который будет принимать данные от новых девайсов переконвертировать их в формат старых девайсов и отсылать на старый сервер.

Опыта написания серверного ПО нет.

Сначала хочу просто в баше навалять используя netcat, точнее возьму ncat от nmap...

Надо чтобы сервер слушал порт, при конекте запускал дочерный процесс который устанавливал соединение и запускал баш скрипт для переконвертации данных, потом результат перенаправлял в «клиентскую» часть которая должна установить соединение со старым сервером и передавать ему данные. Весь этот дочерный процесс не должен прекращать работу сам, а только если обрывается связь со старым сервером или девайсом.



Последнее исправление: JonSmith (всего исправлений: 1)

В чём проблема?

Deleted
()

Я за тебя рад. Пиши.

Zhbert ★★★★★
()

Ну что я могу сказать. Только «БУГАГАГАГА».

ECLIPSE
()
:; while [ $? -eq 0 ]; do nc -vlp 8080 -c'(r=read; e=echo;$r a b c; z=$r; while [ ${#z} -gt 2 ]; do $r z; done; f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`; h=«HTTP/1.0»; o=«$h 200 OK\r\n»; c=«Content»; if [ -z $f ]; then($e $o; ls|(while $r n; do if [ -f «$n» ]; then $e «`ls -gh $n`»; fi; done);); elif [ -f $f ]; then $e «$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`»;$e; cat $f; else $e -e «$h 404 Not Found\n\n404\n»; fi)'; done

Держи сервер.

dizza ★★★★★
()

Анонимус благословляет.

anonymous
()

Я рад что все так быстро отозвались но я только теперь сформулировал вопрос :)))

JonSmith
() автор топика

Зачем Вам форки/треды, межпроцессное взаимодействие и проч. горе от ума? Слушающий сервер на select'е принимает пакеты данных и складывает каждый пакет в отдельный файл. Отдельная, независимая, прога читает файлы, преобразует формат, отправляет на старый сервер, стирает файл. Усе. Бонус - буферизаци данных на диск на случай падения старого сервера.

Кстати, если не секрет, что за сервер? Писал такую фигню для GPS мониторинга.

imatveev13
()
Ответ на: комментарий от ananas

в bash есть специальные файлы /dev/tcp/<host>/<port> - не нужно городить какие-то сервера.

У меня например нету, дистр Altlinux 5.0

pavel38
()
Ответ на: комментарий от imatveev13

>Слушающий сервер на select'е принимает пакеты данных и складывает каждый пакет в отдельный файл.

Подробней? Непользовал селект. я и tcpdump могу пакеты в файл ваять.. netcat он в нормальном ANCI кодировании текст выдаёт.

JonSmith
() автор топика
Ответ на: комментарий от ananas

>в bash есть специальные файлы /dev/tcp/<host>/<port> - не нужно городить какие-то сервера.

ncat - безопаснее поддерживает шифрование и имеет неограниченные возможности в этом деле.

JonSmith
() автор топика
Ответ на: комментарий от pavel38

В ман баш написано что еси есть то баш пытается открыть соединение при редиректе. Наверно надо создать, у дженты тоже нет.

JonSmith
() автор топика
Ответ на: комментарий от JonSmith

> А безопасность таких вещей? Баш на порт вешать...

я так понял, тебе просто макет накидать надо, чтобы проверить работоспособность схемы. так не стоит раньше времени безопасностью заморачиваться

ananas ★★★★★
()
Ответ на: комментарий от ananas

>я так понял, тебе просто макет накидать надо, чтобы проверить работоспособность схемы. так не стоит раньше времени безопасностью заморачиваться

да, __безопасный__ макет для проверки работоспособности :)

потом перепишу на С

JonSmith
() автор топика
Ответ на: комментарий от JonSmith

Ваще select системная функция, man select. В кратце: даешь селекту массив дескрипторов, файлы/сокеты, ему пофиг. А он рассказывает какие у дескрипторов были события. В нете куча примеров серверов на селекте.

Например так:

int sock;  /* The socket file descriptor for our "listening" socket */

int connectlist[MAXCONNECTIONS];  /* Array of connected sockets so we know who	we are talking to */

//указатель на кучу дескрипторов кот. надо скармливать select'у
//готовится из connectlist[]
fd_set socks;        /* Socket file descriptors we want to wake	up for, using select() */

int highsock;	     /* Highest #'d file descriptor, needed for select() */

//---------------------------------------------------
void read_socks() {
	int listnum;	     /* Current item in connectlist for for loops */

	/* OK, now socks will be set with whatever socket(s)
	   are ready for reading.  Lets first check our
	   "listening" socket, and then check the sockets
	   in connectlist. */
	
	/* If a client is trying to connect() to our listening
		socket, select() will consider that as the socket
		being 'readable'. Thus, if the listening socket is
		part of the fd_set, we need to accept a new connection. */
	
	if (FD_ISSET(sock,&socks))
		handle_new_connection();
	/* Now check connectlist for available data */
	
	/* Run through our sockets and check to see if anything
		happened with them, if so 'service' them. */
	
	for (listnum = 0; listnum < MAXCONNECTIONS; listnum++) {
		if (FD_ISSET(connectlist[listnum],&socks)){
			
			//DBGMSG("reading connection:%d\n", listnum);
			
			//if FD_ISSET says there is data for us and there is non, something is wrong
			//close connection
			if( !deal_with_data(listnum) ){ 
				//DBGMSG("FD_ISSET says there is data for us and there is non, closing connection:%d\n", listnum);
				//close_connection(listnum);
				return;
			}
		}
	} /* for (all entries in queue) */
}

//---------------------------------------------------
void handle_new_connection() {
	int listnum;	     /* Current item in connectlist for for loops */
	int connection; /* Socket file descriptor for incoming connections */

	/* We have a new connection coming in!  We'll 	try to find a spot for it in connectlist. */
	connection = accept(sock, NULL, NULL);
	if (connection < 0) {
		//perror("accept");
		ERRMSG("accept:%s\n", strerror (errno));
		exit(EXIT_FAILURE);
	}
	setnonblocking(connection);
	for (listnum = 0; (listnum < MAXCONNECTIONS) && (connection != -1); listnum ++)
		if (connectlist[listnum] == 0) {
			//printf("\nConnection accepted:   FD=%d; Slot=%d\n",	connection,listnum);
			DBGMSG("\nConnection accepted:   FD=%d; Slot=%d\n",	connection,listnum);
			connectlist[listnum] = connection;
			connection = -1;
			connectlist_last_act_time[listnum] = time(NULL);
		}
	if (connection != -1) {
		/* No room left in the queue! */
		//printf("\nNo room left for new client.\n");
		ERRMSG("No room left for new client.\n","");
		//sock_puts(connection,"Sorry, this server is too busy. Try again later!\r\n");
		close(connection);
	}
}


//---------------------------------------------------
int deal_with_data(const int listnum) {/* Current item in connectlist for for loops */

	char rx_buffer[STRBUFLEN+1];     /* Buffer for socket reads */
	char strbuf[STRBUFLEN+1];
//	char *cur_char;      /* Used in processing buffer */
	//unsigned long	IMEI;
	long long	IMEI;
	DIR	*	dir_p;
	struct	dirent *dir_entry_p;
	char *	IMEI_str_p;
	FILE *	new_packet_file;
	char	new_packet_fname[STRBUFLEN+1];
	time_t	packet_rx_time;
	struct tm * packet_rx_time_local;
	//struct tm    	packet_rx_time_local;
	
	int ret_val=0;
	int q;
	
	bzero(rx_buffer, STRBUFLEN+1);

	ret_val=sock_gets(connectlist[listnum], rx_buffer, STRBUFLEN);
	if (  ret_val < 0) {
		//Connection closed, close this end and free up entry in connectlist 
		DBGMSG("\nConnection lost FD:%d Slot:%d ret_val:%d IMEI:%s\n", connectlist[listnum], listnum, ret_val, connectlistIMEI[listnum]);
		close_connection( listnum );
		return(0);
	} 
	
	if( ret_val == 0 ){
		//dbgmsg("empty packet\n");
		DBGMSG("FD_ISSET says there is data for us and there is non, closing connection:%d IMEI:%s\n", listnum, connectlistIMEI[listnum]);
		close_connection(listnum);
		return(0);
	}
//Сделать с полученными в rx_buffer данными что надо
}

//-------------------------------------
main(){
	
	/* Obtain a file descriptor for our "listening" socket */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		//perror("socket");
		ERRMSG("socket:%s\n", strerror (errno));
		exit(EXIT_FAILURE);
	}
	/* So that we can re-bind to it without TIME_WAIT problems */
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,	sizeof(reuse_addr));

	/* Set socket to non-blocking with our setnonblocking routine */
	setnonblocking(sock);

	/* Get the address information, and bind it to the socket */
	memset((char *) &server_address, 0, sizeof(server_address));
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = htonl(INADDR_ANY);
	server_address.sin_port = htons(port);
	//printf("port:%d server_address.sin_port:%d\n", port,server_address.sin_port);
	if (bind(sock, (struct sockaddr *) &server_address,	  sizeof(server_address)) < 0 ) {
		//perror("bind");
		ERRMSG("bind:%s\n", strerror (errno));
		close(sock);
		exit(EXIT_FAILURE);
	}

	/* Set up queue for incoming connections. */
	listen(sock, MAXCONNECTIONS);

	/* Since we start with only one socket, the listening socket, it is the highest socket so far. */
	highsock = sock;
	memset((char *) &connectlist, 0, sizeof(connectlist));

	while (1) { /* Main server loop - forever */
		build_select_list();
		//timeout.tv_sec = 1;
		timeout.tv_sec = 0;
		timeout.tv_usec = 1000;
		
		
		readsocks = select(highsock+1, &socks, (fd_set *) 0, (fd_set *) 0, &timeout);
		
		/* select() returns the number of sockets that had
			things going on with them -- i.e. they're readable. */
			
		/* Once select() returns, the original fd_set has been
			modified so it now reflects the state of why select()
			woke up. i.e. If file descriptor 4 was originally in
			the fd_set, and then it became readable, the fd_set
			contains file descriptor 4 in it. */
		
		if (readsocks < 0) {
			//perror("select");
			ERRMSG("select:%s\n", strerror (errno));
			exit(EXIT_FAILURE);
		}
		if (readsocks == 0) {
			/* Nothing ready to read, just show that  we're alive */
		} 
		else{
			read_socks();
			IMEI_connected_report();
		}

	} /* while(1) */
} /* main */

imatveev13
()

Надо чтобы сервер слушал порт, при конекте запускал дочерный процесс который устанавливал соединение и запускал баш скрипт для переконвертации данных, потом результат перенаправлял в «клиентскую» часть которая должна установить соединение со старым сервером и передавать ему данные. Весь этот дочерный процесс не должен прекращать работу сам, а только если обрывается связь со старым сервером или девайсом.


socat TCP4-LISTEN:5555,fork,tcpwrap=script \
EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr

a simple server that accepts connections (TCP4-LISTEN) and fork's a new child process for each connection; every child acts as single relay. The client must match the rules for daemon process name «script» in /etc/hosts.allow and /etc/hosts.deny, otherwise it is refused access (see «man 5 hosts_access»). For EXEC'uting the program, the child process chroot's to /home/sandbox, su's to user sandbox, and then starts the program /home/sandbox/bin/myscript. Socat and myscript communicate via a pseudo tty (pty); myscript's stderr is redirected to stdout, so its error messages are transferred via socat to the connected client.

zensey
()

man xinetd

я на нем подобными вещами извращался.

а вообще если текст сношать, то рекомендую сделать простенький сервер на перле, далее регекспами парсить

simple_best_world_web_master
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.