LINUX.ORG.RU

1
Всего сообщений: 80

icmpv6 raw sockets в pyhon

Как пользоваться сабжем? Как я понимаю, чтобы послать валидный пакет, надо считать его контрольную сумму. А она считается вместе с заголовками пакета ip, который недоступен.

python-pcs решает эту проблему через libpcap формируя пакеты на уровне ethernet, но это извращение.

В исходниках линуксного ping6.c они включают опцию IPV6_CHECKSUM и сетевой стек всё считает сам, что несомненно логично. Но как её включить в python’e?

 , ,

alt-x ()

Сокеты

Здравствуйте! Помогите, пожалуйста со следующей проблемой. У меня есть готовый код, описывающий взаимодействие клиент-сервер. Но он работает как общий чат.То есть при отправке сообщения на сервер это сообщение видят все клиенты. Этот код нужно доработать, так чтобы клиент мог выбирать адресата из списка всех клиентов и общаться только с ним. Можете подсказать как это организовать? Или какие ошибки исправить в коде?

Код сервера:

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

#include <strings.h>

#include <poll.h>
#define IPADDRESS "127.0.0.1"
#define PORT 6666
#define MAXLINE 1024
#define LISTENQ 5
#define OPEN_MAX 1000
#define INFTIM -1

int bind_and_listen()
{
	int serverfd;
	struct sockaddr_in my_addr;
	unsigned int sin_size;
	if((serverfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		printf ("error socket");
		return -1;
	}
	printf("socket ok\n");
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(PORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(my_addr.sin_zero), 0);
	if(bind(serverfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
	{
		printf("error bind");
		return -2;
	}
	printf("bind ok\n");
	if(listen(serverfd, LISTENQ) == -1)
	{
		printf("error listen");
		return -3;
	}
	printf("listen ok\n");
	return serverfd;
}

void do_poll(int listenfd)
{
	int connfd, sockfd;
	struct sockaddr_in cliaddr;
	socklen_t cliaddrlen;
	struct pollfd clientfds[OPEN_MAX];      
	int maxi;
	int sin_port2[5];
	int i,j;
	int nready;
	clientfds[0].fd = listenfd;
	clientfds[0].events = POLLIN;
	for(i = 1; i<OPEN_MAX; i++)
		clientfds[i].fd = -1;
	maxi = 0;

	while(1)
	{
		nready = poll(clientfds, maxi+1, INFTIM);
		if(nready == -1)
		{
			printf("poll error");
			exit(1);
		}
		if(clientfds[0].revents & POLLIN)
		{
			cliaddrlen = sizeof(cliaddr);
			if((connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen)) <0)
			{
				
					printf("accept error");
					exit(1);
				
			}
			fprintf(stdout, "accept a new client:%s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
			for(i = 1; i<OPEN_MAX; i++)
			{
				if(clientfds[i].fd<0)
				{
					clientfds[i].fd = connfd;
					break;
				}
			}
			if(i == OPEN_MAX)
			{
				fprintf(stderr, "too many clients.\n");
				exit(1);
			}
			sin_port2[i]=cliaddr.sin_port;
			clientfds[i].events = POLLIN;
			maxi = (i>maxi?i:maxi);
			if(--nready<=0)  
				continue;
		}
		
		char buf[MAXLINE];
                char BUF[80];
		
		memset(buf, 0, MAXLINE);
		int readlen = 0;
		for(i = 1; i<maxi; i++)    
		{
			if(clientfds[i].fd<0) continue;
				
			if(clientfds[i].revents & POLLIN)
			{
				readlen = read(clientfds[i].fd, buf, MAXLINE);
				if(readlen == 0)
				{
					close(clientfds[i].fd);
					clientfds[i].fd = -1;
					continue;
				}
				printf("msg is:");
				
				memset(BUF,0,sizeof(BUF));
				sprintf(BUF,"%d :%s",sin_port2[i],buf);
				printf("%s",BUF);
				
                                for(j=1;j<maxi;j++)
				{
				if(i!=j){
				write(clientfds[j].fd, BUF, sizeof(BUF));
				}
				}
	                                
			}
		}
	}
}
int main(int argc, char* argv[])
{
	int listenfd = bind_and_listen();
	if(listenfd<0)
	{
		return 0;
	}
	do_poll(listenfd);
	return 0;
}

Код клиента:


#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<poll.h>
#define IPADDRESS "127.0.0.1"
#define PORT 20113
#define MAXLINE 1024
#define max(a, b) (a>b)?a:b
static void handle_connection(int sockfd);
int main(int argc, char* argv[])
{
	int connfd = 0;
	int clen = 0;
	struct sockaddr_in client;
	if(argc<2)
	{
		printf("Usage: clientent[server IP address]\n");
		return -1;
	}
	client.sin_family = AF_INET;
	client.sin_port = htons(PORT);
	client.sin_addr.s_addr = inet_addr(argv[1]);
	connfd = socket(AF_INET, SOCK_STREAM, 0);
	if(connfd<0)
	{
		printf("error socket");
		return -1;
	}
	if(connect(connfd, (struct sockaddr*)&client, sizeof(client))<0)
	{
		printf("error connect");
		return -1;
	}
	handle_connection(connfd);
	return 0;
}

static void handle_connection(int sockfd)
{
	char sendline[MAXLINE], recvline[MAXLINE];
	int maxfdp, stdineof;
	struct pollfd pfds[2];
	int n;
	pfds[0].fd = sockfd;
	pfds[0].events = POLLIN;
	pfds[1].fd = STDIN_FILENO;
	pfds[1].events = POLLIN;
	while(1)
	{
		poll(pfds, 2, -1);
		if(pfds[0].revents & POLLIN)
		{
			n = read(sockfd, recvline, MAXLINE);
			if(n == 0)
			{
				fprintf(stderr, "client: server is closed.\n");
				close(sockfd);
			}
			write(STDOUT_FILENO, recvline, n);
		}
		if(pfds[1].revents & POLLIN)
		{
			n = read(STDIN_FILENO, sendline, MAXLINE);
			if(n == 0)
			{
				shutdown(sockfd, SHUT_WR);
				continue;
			}
			write(sockfd, sendline, n);
		}
	}
}

[code = C]

 , , ,

art_em ()

Проблема в sockstat sockets: used

Доброго времени суток. Интересует такой вопрос, что значит поле alloc в /proc/net/sockstat , если можно то подробно рассказать, на просторах интернета находил только пару слов.

А так же я не могу понять почему мой сервер выдает такую статистику: sockets: used 109602 TCP: inuse 350 orphan 18 tw 210 alloc 79683 mem 1072 UDP: inuse 43 mem 117 UDPLITE: inuse 0 RAW: inuse 8 FRAG: inuse 0 memory 0

Откуда берется значение sockets: used 109602 проверяя netstat установленные соединения их в помине столько нету. Кто может подсказать, мб есть какая проблема?

 

r6_screm ()

node.js через tcp socket отправить несколько запросов и разделить ответы

В PHP:

fsockopen(....);
fwrite($handle, 'message1\r\n');
// и можем сразу получить ответ, если надо.
fgets($handle);
fwrite($handle, 'message2\r\n');
fgets($handle);
fwrite($handle, 'message3\r\n');
fgets($handle);

в node.js

let net = require('net');
let client = new net.connect(1234,'127.0.0.1', {
  client.write('message1\r\n');
  client.write('message2\r\n');
  client.write('message3\r\n')
});

client.on('data', function (data) {
// сюда ссыпаются ответы.
});

Вопрос: можно ли как-то кроме data.toString().split их разделить либо некоторые ответы игнорировать, т.е. не читать в data?

 , ,

sniper21 ()

Как проверить, есть ли байты в буфере

На вход программе (через Unix Domain Socket или через stdin) приходит сообщение произвольной длины, после чего отправитель ожидает ответа.

Так как сообщение произвольной длины, не получается использовать read(length) или recv(length) — если длина сообщения окажется кратной length, то случится взаимоблокировка (клиент ждёт ответа, сервер ждёт продолжения сообщения).

Решением было бы посмотреть, есть ли в буфере байты.

man ioctl предлагает такое решение:

while ((ioctl(sock, I_NREAD, &num) >= 0) && num > 0)
    /* дописать даные из буфера ввода в буфер в памяти */

, но это не работает для stdin (ошибка ENOTTY):

if ((ioctl(0, I_NREAD, &num) >= 0) && num > 0) /* ошибка ENOTTY */

Есть ли общий способ? Или для сокета и для stdin обязательно надо применять разные подходы (если так, то какие)?

EDIT: пример кода «клента» (на пхп):

$proc_handle = proc_open('./run', [['pipe', 'r'],['pipe', 'w']], $pipes);

foreach ($test_cases as $request => $response)
{
    echo "Test: ".$request;
    fwrite($pipes[0], $request);
    fflush($pipes[0]);

    echo "Answer: ".fgets($pipes[1]);
    echo "\n";
}

EDIT: Пример решения: перевод stdin в неблокирующий режим (подсказал u/Elyas, решение взято с https://stackoverflow.com/a/30548692):

#include <stdio.h>

#include <unistd.h>
#include <fcntl.h>

static int counter = 0;

void updatecounter(void)
{
	int n;
	char buf[100];
	while (1)
	{
		if ((n = read(0, buf, 100)) <= 0) break;
		counter += n;
	}
}

int main(void)
{
	fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);

	while (1)
	{
		updatecounter();
		printf("%d\n", counter);
		sleep(2);
	}

	return 0;
}

EDIT: Пример решения: использование poll (подсказал u/mittorn):

#include <stdio.h>

#include <unistd.h>
#include <poll.h>

static int counter = 0;

void updatecounter(void)
{
	char buf[100];
	struct pollfd pollfds[1] = {0, POLLIN, 0};

	while (1)
	{
		if (!poll(pollfds, 1, 0)) break;
		counter += read(0, buf, 100);
	}
}

int main(void)
{
	while (1)
	{
		updatecounter();
		printf("%d\n", counter);
		sleep(2);
	}

	return 0;
}

EDIT: решение от u/kardapoltsev : указывать длину сообщения перед его началом

EDIT: оба решения проверены на сокетах.

 , , ,

peterstein ()

как спроектировать такое приложение?

В браузере должно отображаться состояние прибора постоянно- желательно как можно ближе к RT с поправкой на сеть разумеется. К прибору подключаться по TCP сокетам.

Сейчас сделано так

Web browser <----AJAX-----> Apache+PHP <---TCP sockets------> Прибор

Браузер говорит что ему надо данных, php получает от браузера запрос, и открывает соединение с прибором полуает данные и отправляет в браузер. PHP не принципиально.

Вопрос: как такое лучше сделать чтобы каждый раз не отправлять запрос из браузера, но при этом получать данные с устройства постоянно? Web sockets?

 , ,

sniper21 ()

Мой прокси сервер слишком медленный

Ребята, возникла задача написать прокси сервер под линуксы на сишке. Вот я написал и сервак очень сильно лагает, тупит и не может загрузить ютуб видео банально. Ребята, помогите, я не знаю почему он такой медленный, я вроде все по потокам разбил (на каждый поток по 64 сокета) и юзаю асинхронные сокеты для poll'инга

Буду благодарен если вы хотя-бы просто посмотрите и подскажите что мне переделать

Вот исходник https://pastebin.com/yMSNJcCz

 , , , ,

MikkotoNikki ()

Пинг-Понг пересылка для поддержки конекта

Приветствую участников форума! Вопрос по большей части относительно фаерволов.
Разрабатывается простой клиент-серверный сервис, клиент подключается по протоколу tcp к этому сервису и устанавливается соединение, но как-бы данные не пересылаются, а просто клиент ожидает поступления данных от сервера.
Стоит ли ожидать каких либо действий со стороны фаервола в отношении таких соединений?
Думаю сделать типа пинг-понг пересылку с интервалом для ожидающих клиентов до поступления целевых данных, потом как только пересылка важных данных закончена, опять переводить в пинг-понг режим до поступления очередной порции данных.

 

domik_v_derevne ()

Ищу «конденсатор данных» по передаче данных в сеть в плохих условиях

Собственно проблема такая:

Есть пачка нод какого-то приложения, которые что-то пишут на главную мастер ноду. Между главной нодой и этой пачкой - большой кусачий интернет. Я ищу уже готовые решения, которые можно было бы использовать для накопления данных на нодах, не изменяя ПО а только натройки отправки, и отправкой их на мастер ноду при первой же возможности. Этакий прокси-конденсатор.

Хоть задача кажется и простой с точки зрения программирования - но по опыту знаю что там докучи вылезет приколов.

 , ,

visual ()

Правильное использование сокетов

Есть 2 процесса, в одном из которых хранится некий список структур с данными, а второй должен получать эти данные от первого и выводить в терминал. После раскуривания мануалов по работе с сокетами для реализации этого всего возникло несколько вопросов, ответ на которые хотелось бы услышать от живых людей.
Что есть более unix-way решением: формировать вывод на стороне первого процесса и передавать в сокет в виде строк, чтобы второму оставалось только прочитать из сокета и вывести то, что получил, либо же передавать сокетом структуры в бинарном виде, а на стороне второго процесса их обрабатывать и потом уже выводить? Либо же оба решения применимы и не будут в итоге торчать костылём? А также, возможно есть какие-то преимущества в датаграммном или потоковом сокетах для данной задачи, либо же оба одинаково эффективно можно использовать, при учёте, что вся передача будет на одном хосте?
Данные, если что, первый процесс должен пересылать после получения команды от второго. Вот.
Буду благодарен за советы касательно этого вопроса.

 , , , ,

Reineke ()

sk_buff - линейный буффер и skb_shared_info

Насколько я понимаю, sk_buff поддерживает возможность помещать данные линейно, а также странично, то есть нелинейно. «Страничность» определяется структурой skb_shared_info, которая помещается сразу после skb. Вопрос — гарантирует ли ядро минимальное количество байт, которые могут быть размещены в линейной области?

 , , ,

cruz7 ()

библиотека для TCP/IP сокет подключений

Собственно, порекомендуйте, пожалуйста, библиотеку для TCP/IP сокет.

cURL?

есть ещё что?

А, да, условие: поддержка GNU/Linux, MS Windows

Язык: С++

 , ,

sniper21 ()

Дебаг соединения

Всем привет! Суть такова: есть веб-приложение на java, перед ним стоит Nginx, как реверс-прокси, рулит ssl-сертификатами. Когда заходишь на сервак из браузера или посылаешь запрос постманом, всё проходит ок, когда заходишь с iPad (там своё специальное приложение) то залогиниться невозможно, причём запрос ест ьв логах Nginx, но его нет в логах приложения. iptables чисты как слеза младенца, есть даже второй сервак с такой же конфигурацией и на нём всё работает нормально! ПРоверили всё по 10 раз, в чём проблема непонятно! Подскажите инструмент, которым можно разобрать по косточкам, что происходит с запросом на nginx или что-то подобное, девелоперы упирали на fiddler, но он хочет xorg на сервере, а я не осилил его поставить на тачку без монитора и вообще так и не разобрался до конца в его архитектуре. Буду рад любой наводке!

 , ,

Pyzia ()

получить pid процесса владеющего сокетом

В моем приложении мне нужно получить PID процесса владеющего сокетом. Пока что вижу единственный вариант: пройти по всем /proc/PID/fd/*, прочитать readlink() все записи типа socket:[inode], и потом по иноду получить fd сокета.

Но есть ли способ проще? Я не нашел syscall'a который бы это делал, может быть плохо искал, или есть причины по которым его не реализовали? (болошой оверхед и пр.)

Спасибо.

 , , ,

cruz7 ()

Как найти заголовок в текстовых протоколах?

Как считывать данные и искать заголовки из текстовых протоколов? Вроде HTTP? Я отправляю запрос в сокет.

Мне приходит ответ

HTTP/1.0 200 OK
Server: nginx/0.6.31
Content-Language: ru
Content-Type: text/html; charset=utf-8
Content-Length: 1234

<данные>

Каким образом я должен узнать сколько байт будет в заголовке ответа сервера, чтобы его полностью распарсить?

Считывать побайтово пока не встречу \r\n\r\n?

Мне кажется, побайтово считывать медленно.

 , , ,

JANB ()

Сокеты - Несовпадение длины пакетов MJPEG при чтении

Есть сервер который читает по 255 байт MJPEG поток и сразу их же по 255 байт отправляет на заданный ip (другой сервер)

std::stringstream requestQuery;
requestQuery << "GET /axis-cgi/mjpg/video.cgi?resolution=320x240 HTTP/1.1\r\n"
             << "Host: 88.53.197.250\r\n"
             << "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
             << "\r\n\r\n";
std::string request = requestQuery.str();

// sock - источник MJPEG
if (send(sock, request.c_str(), request.length(), 0) != (int)request.length()) {
    std::cout << "Error sending request." << std::endl;
    exit(1);
}

char buffer[256];
char cur2;
while (1) {
    bzero(buffer,256);
    size_t n = read(sock,buffer,255);
    if (n < 0)
        printf("ERROR reading from socket\n");
    size_t n2 = write(sockServ,buffer,255);  // sockServ - приемник MJPEG
}

Данные приходят, я их вижу они выглядят так

HTTP/1.1 200 OK\r\n
Cache-Control: no-cache\r\n
Pragma: no-cache\r\n
Expires: Thu, 01 Dec 1994 16:00:00 GMT\r\n
Connection: close\r\n
Content-Type: multipart/x-mixed-replace; boundary=--myboundary\r\n
\r\n
--myboundary\r\n
Content-Type: image/jpeg\r\n
Content-Length: 8530\r\n
\r\n
(тут пошли данные)

На заданном IP есть другой сервер.

Я открываю сокет, жду подключения (accept) и пытаюсь считать данные. Вначале считываю общий заголовок, Потом заголовок первого маркера "--myboundary" до значения длины, потом саму длину

bzero(buffer,512);
n = read(newsockfd,buffer,185); // общий заголовок
if (n < 0) error("ERROR reading from socket");
// printf("%s\n",buffer);

while(1) {
    bzero(buffer, 512);
    n = read(newsockfd, buffer, 56); // заголовок с --myboundary
    printf("HEADER:\n",buffer);
    printf("%s\n",buffer);// вывожу заголовок
    if (n < 0) error("ERROR reading from socket");
    bzero(filesizetext,20);
    int i = 0;
    while(1) {
        n = read(newsockfd, &ch, 1); // по одному символу до конца строки считываю значение Content-Length
        if (n < 0) error("ERROR reading from socket");
        if (ch == '\r')
            break;
        filesizetext[i] = ch;
        i++;
    }
    int currFileSize = atoi(filesizetext); // преобразую Content-Length в число
    n = read(newsockfd, buf, currFileSize); // считываю Content-Length байт
    if (n < 0) error("ERROR reading from socket");

	// идем дальше, снова считывать заголовок  с --myboundary
}

Когда доходим до «идем дальше, снова считывать заголовок с --myboundary» Вместо заголовка выводятся кракозябры - значит данные еще не кончились, и мы считали раньше чем нужно.

1) Чем может объясняться несовпадиние длины данных?

2) Можно ли с писать в сокет по 512 байт, а читать переменное количество?

 , , ,

JANB ()

Как потоком сжимать данные, отправлямые в сокет?

Попробовал IO::Compress::Gzip->new($sock) - что-то не работает оно так совсем. Уж и autoflush ставил, и убирал - ничего не помогает :(

Вообще насколько я помню, основные алгоритмы сжатия основаны на словарях - по логике, чем больше нужно клиенту данных отправить в сжатом виде, тем обширнее словарь, но в таком случае помимо самих данных нужно с каждой новой порцией сжатого потока выдавать ещё и обновления словаря, если они вообще есть.

Искал в гугле IO::Compress::Gzip socket - ничего не нашёл.

Если сжимать данные теми «кусочками», которыми они дискретно формируются - получится невыгодно, поскольку кусочки просто мизерные, есть смысл сжимать всё это только как поток.

Ну и в целом - есть ли вообще какая-то общеизвестная методика, как сжимать ответы и отправлять их в сокет? У меня всё отлично работает в ту сторону: исходные данные клиента жмутся, всё ОК. Но вот в обратку/ответами что-то какой-то лютый треш происходит: приходит только небольшая порция неконсистентных данных.

 , ,

DRVTiny ()

Сокет не отправляет данные на сервер

Если запустить нижеследующий код на perl'е, то в консоли выводится «rc=12», но строка «Hello World» на сервер не приходит.

my $client = IO::Socket::INET->new("localhost:8080");
my $rc = $client->send("Hello World!");
print "rc=$rc\n";

Сниффер показывает что соединение устанавливается, но передачи данных нет. Пробовал явно выставлять autoflush, но не помогло (да и в документации сказано что autoflush уже выставлен по умолчанию). А вот если отсылаемую строку завершить переводом строки, то данные отправляются. Что нужно поправить в коде чтобы работало без перевода строки?

 ,

ricie ()

как реализовать проверку наличия ожидающих соединения клиентских сокетов

здравствуйте, в c# есть класс tcpListener, реализующий логику работы с серверным сокетом(bind, listen, accept)... там есть метод Pending, осуществляющий проверку наличия ожидающих на соединения клиентских сокетов https://msdn.microsoft.com/ru-ru/library/system.net.sockets.tcplistener.pending(v=vs.110).aspx... подскажите, как сделать проверку наличия ожидающих соединения клиентских сокетов на си? accept же метод только возвращает дескриптор нового сокета для общения с клиентом... а дальше не знаю что делать

 ,

xperious ()

получить socket fd из "struct sock"

Приветствую,

Есть ли возможность из объекта типа 'struct sock' получить дескриптов сокета, полученный пользователем послен выполнения socket()?

 , , , ,

cruz7 ()