LINUX.ORG.RU

передача списка процессов сервера клиенту

 , , ,


0

1

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

/************************************************/
/*	server.c - простой TCP/IP сервер	*/
/************************************************/

//подключаем необходимые заголовчные файлы
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>

extern errno; 	//глобальная переменная, которая хранит код последней ошибки

//проверка, задан ли шаблон INADDR_NONE, который обозначает сразу все доступные сетевые интерфейсы
//на некоторых платформах, он может быть не задан.
#ifndef INADDR_NONE
#define INADDR_NONE 0xfffffffff
#endif

//функция создания и связывания сокета. объявление
//аргументы:
//port - порт, с которым связывается сервер
//transport - протокол, по которому будет работать сервер (tcp или udp)
//qlen - длина  очереди
int sock(const char *port, const char *transport, int qlen);

//главная функция
int main()
{
    int msock, csock;				//дескрипторы сокетов
    struct sockaddr_in  remaddr;			//структура IP-адреса клиента
    unsigned int remaddrs = sizeof(remaddr);	//размер структуры адреса
    char msg[21];					//буфер сообщения
    FILE *output;
    int i;

    msock = sock("1231", "tcp", 5);	//создаем tcp сокет и привязываем его к порту 3123, задав очередь 5
    if(msock < 0)			//проверяем значение дескриптора сокета
        return -1;		//завершаем программу

    while(1)	//бесконечный цикл
    {
        csock = accept(msock, (struct sockaddr*) &remaddr, &remaddrs);	//принимаем входящее подключение, адрес клиента в remaddr
        if(csock < 0)		//проверяем результат
            printf("Ошибка принятия подключения: %s\n", strerror(errno)); //сообщение об ошибке
        else			//если все нормально - начинаем обмен данными с клиентом
            {
                if(read(csock, &msg, sizeof(msg)) >0 )		//пробуем читать данные от клиента
                {
                    if(strstr(msg, "hello"))			//если получено "hello"
                    {
                        memset(&msg, 0, sizeof(msg));			//обнуляем буфер
                        strcpy(msg, "hello, ");				//формируем строку ответа
                        output = popen("ps -aux","w");
                        strcat(msg, inet_ntoa(remaddr.sin_addr));	//преобразовываем адрес клиента в строку
                        strcat(msg, " !!!\n\0");			//завершаем строку ответа
                        write(csock, msg, sizeof(msg));			//отсылаем ответ
                        write(csock, output,sizeof(output));
                    }
                }
                close(csock);		//закрываем сокет клиента
                pclose(output);
            }
    }
    close(msock);		//закрываем сокет сервера
    return 0;
}

//функция создания и связывания сокета. реализация
int sock(const char *port, const char *transport, int qlen)
{
    struct protoent *ppe;
    struct sockaddr_in sin;
    int s, type;
    //обнуляем структуру адреса
    memset(&sin, 0, sizeof(sin));
    //указываем тип адреса - IPv4, для IPv6 необходимо указать AF_INET6
    sin.sin_family = AF_INET;
    //указываем, в качестве адреса, шаблон INADDR_ANY - все сетевые интерфейсы
    sin.sin_addr.s_addr = INADDR_ANY;
    //задаем порт
    sin.sin_port = htons((unsigned short)atoi(port));
    //преобразовываем имя транспортного протокола в номер протокола
    if((ppe = getprotobyname(transport)) == 0)
        {
            printf("Ошибка преобразования имени транспортного протокола: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //используем имя протокола для определения типа сокета
    if(strcmp(transport, "udp") == 0)
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;
    //создаем сокет
    s = socket(PF_INET, type, ppe->p_proto);
    if(s < 0)
        {
            printf("Ошибка создания сокета: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //привязка сокета с проверкой результата
    if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        {
            printf("Ошибка связывания сокета: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //запуск прослушивания с проверкой результата
    if(type == SOCK_STREAM && listen(s, qlen) <0)
        {
            printf("Ошибка прослушивания сокета: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    return s;	//возвращаем дескриптор сокета
}
/************************************************/
/*	client.c - простой TCP/IP клиент	*/
/************************************************/

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

extern errno; 	//глобальная переменная, которая хранит код последней ошибки

//функция подключения к серверу. объявление
//аргументы:
//host - адрес (имя) сервера
//port - порт сервера
//transport - протокол tcp или udp
int connectsock(const char *host, const char *port, const char *transport);

//главная функция
int main(int argc, char **argv)
{
    int sock; 	//сокет
    char msg[1000];	//буфер сообщения
    int i;

    if(argc == 3) 	//проверяем количество переданных аргументов.
    {
        //подключаем сокет, в качестве хоста - первый аргумент программы, в качестве порта - второй аргумент программы
        //напомню, что в argv[0] хранится имя самого исполняемого файла программы, поэтому его опускаем.
        sock = connectsock(argv[1], argv[2], "tcp");
        if(sock < 0)	//проверяем дескриптор сокета
            return -1;
        else 		//подключились
            {
                printf("Установлено соединение с %s:%s\n", argv[1], argv[2]);
                strcpy(msg, "hello\0");		//подготавливаем строку сообщения
                if(write(sock, msg, sizeof(msg)) < 0)		//отсылаем серверу
                    {
                        printf("Не удалось отправить данные серверу: %s\n", strerror(errno));
                        return -1;
                    }
                printf("Серверу отправлен \"hello\"\n");	//читаем ответ сервера
                memset(&msg, 0, sizeof(msg));
                if(read(sock, msg, sizeof(msg)) < 0)
                    {
                        printf("Не удалось отправить данные серверу: %s\n", strerror(errno));
                        return -1;
                    }
                else				//выводим ответ сервера
                    printf("От сервера получено: %s\n", msg);
                FILE *output;
                read(sock, output, 8);
                for (i = 0; i < 100; i++)
                  fprintf (output, "%d\n", i);
            close(sock);	//закрываем сокет
            }

    } else	//иначе
        printf("Использование: server \"server\" \"port\"\n");	//выводим подсказку по использованию.
    return 0;
}

//функция подключения к серверу. реализация
int connectsock(const char *host, const char *port, const char *transport)
{
    struct hostent *phe; //указатель на запись с информацией о хосте
    struct servent *pse; //указатель на запись с информацией о службе
    struct protoent *ppe; //указатель на запись с информацией о протоколе
    struct sockaddr_in sin; //структура IP-адреса оконечной точки
    int s, type; //дескриптор сокета и тип сокета

    //обнуляем структуру адреса
    memset(&sin, 0, sizeof(sin));
    //указываем тип адреса (IPv4)
    sin.sin_family = AF_INET;
    //задаем порт
    sin.sin_port = htons((unsigned short)atoi(port));
    //преобразовываем имя хоста в IP-адрес, предусмотрев возможность представить его
    //в точечном десятичном формате
    if(phe = gethostbyname(host))
        memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
    //преобразовываем имя транспортного протокола в номер протокола
    if((ppe = getprotobyname(transport)) == 0)
        {
            printf("Ошибка преобразования имени транспортного протокола: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //используем имя протокола для определения типа сокета
    if(strcmp(transport, "udp") == 0)
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;
    //создание сокета
    s = socket(PF_INET, type, ppe->p_proto);
    if(s < 0)
        {
            printf("Ошибка создания сокета: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //попытка подключить сокет
    if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        {
            printf("Не удалось подключится к серверу: %s\n", strerror(errno));	//в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //возвращаем дескриптор подключенного сокета
    return s;
}

Сынок, ты уже взрослый, пора с тобой поговорить о таком понятии как «протокол». Протокол прикладного уровня — это такая херовина, которая описывает «КАК» и является ответом на твой вопрос. А то, что ты выложил - это не протокол и тем более не «почти полностью написан», это просто зачаток клиента из книжки, которая называется «стань супер программером за 10 дней». Это сетевой хеловорд, если хочешь.

anonymous ()

Четай трубу, пеши в сокет.

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

Протоколы не нужны для этих целей. Он просто хочет видеть ps с сервера, не запуская всякие ssh. Можно кстати в 2 строчки на баше + netcat.

mittorn ★★★★★ ()
Последнее исправление: mittorn (всего исправлений: 1)
Ответ на: комментарий от mittorn

Да ты шо? А когда ты по «меткам» определяешь начало, размер и конец файла/данных это не протокол?

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

А когда ты по «меткам» определяешь начало, размер и конец

то ты для этой задачи перебарщиваешь, не?

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

ты для этой задачи перебарщиваешь, не?
передача списка процессов сервера клиенту

Если только это единственное, что может отдавать сервер, то читать до победного конца, считая что все что передано и есть то что надо.

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