Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > SMTP сервер


Автор: mChief 11.11.2009, 11:01
Помогите разобраться с заданием и подскажите с чего начать. Пробвал читать RFC по SMTP, но понимания что именно нужно делать не пришло smile.
Задание звучит так:
Написать программу, которая выполняет функции промежуточного SMTP-сервера. Сервер должен получить инструкции от клиента на передачу почты, добавить в заголовок сообщения информацию о промежуточный сервер и передать сообщение другому SMTP-серверу.

Автор: GrayCardinal 11.11.2009, 11:03
ИМХО, начать надо с простого сквозного TCP сервера. т.е. Получает команды. отправляет на реальный сервер, и всё это логится... Дальше - дело техники. Набросать простой сервак ?

Автор: mChief 11.11.2009, 12:12
Сквозной TCP сервер, я думаю, смогу написать, а как быть дальше? Нужно тогда еще написать псевдо-клиент, который будет отправлять этому серверу готовое письмо с заголовком? И, наверное, еще один псевдо-сервер который будет ловить все эти сообщения, потому как реальные SMTP сервера наверняка меня пошлютsmile

Автор: GrayCardinal 11.11.2009, 12:28
А дальше... Сквозным серваком ловите команду DATA, читаете тело письма, добавляете нужный хидер и шлете дальше...

Автор: mChief 11.11.2009, 12:42
Начинаю понимать. И еще два вороса: Как лучше будет читать данные из сокета если я знаю что шлет их почтовый клиент? Какой нужен размер буфера?

Автор: GrayCardinal 11.11.2009, 15:56
mChief, 
Первый вопрос не понял. Второй... На любителя. Вплоть до мегабайта. Больше я бы не стал smile

Автор: mChief 12.11.2009, 16:40
Неудачно сформулировал первый вопросsmile Я просто хотел узнать есть ли какие-нибудь особенности работы с текстовыми протоколами.

Попробовал написать сквозной сервер, подскажите если что не так

Код

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <resolv.h>
#include <string.h>

#define SERVER_IP "94.100.177.6"
#define PORT 110
#define QUEUE 5
#define BSIZE 2048

int main(){
    int listen_sock,conn_sock,send_sock;
    char buf[BSIZE]={0};
    struct sockaddr_in cli_addr,serv_addr,send_addr;

    send_sock=socket(AF_INET,SOCK_STREAM,0);
    if(!send_sock){
        printf("Can't create send socket\n");
        abort();
    }
    bzero(&send_addr,sizeof(send_addr));
    send_addr.sin_family=AF_INET;
    send_addr.sin_port=htons(PORT);
    char* host=SERVER_IP;
    inet_aton(host, &send_addr.sin_addr);

    listen_sock=socket(AF_INET,SOCK_STREAM,0);
    if(!listen_sock){
        printf("Can't create listen socket\n");
        abort();
    }
    bzero(&serv_addr,sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    bind(listen_sock,&serv_addr,sizeof(serv_addr));
    listen(listen_sock,QUEUE);
    for(;;){
        //clilen=sizeof(cli_addr);
        conn_sock=accept(listen_sock,&cli_addr,sizeof(cli_addr));
        if(!listen_sock){
            printf("Can't create conn socket\n");
            abort();
        }
        int childpid=0;
        if(childpid=fork()==0){
            //потомок
            close(listen_sock);

            if ( connect(send_sock, &send_addr, sizeof(send_addr)) !=0 ){
                perror("Server connection error");
                abort();
            }
            int msgsize=0;
            for(;;){
                msgsize=recv(listen_sock,buf,BSIZE,0);
                if(msgsize==0) exit(0);
                send(send_sock,buf,msgsize,0);
            }
            //exit(0);
        } else {
            //родитель
            close(conn_sock);
        }
    }
    return 0;
}



Как я понимаю теперь в коде потомка нужно ловить команду DATA и править заголовок письма.

Автор: GrayCardinal 12.11.2009, 16:47
Нормально. Только я бы bzero заменил на memset, да результат bind проверил... smile

Добавлено через 59 секунд
На счет особенностей. Знаю одну. Конец строки должен быть 0x0D 0x0A. В *nix используется только 0x0A. 0x0D надо ручками добавлять.....

Автор: mChief 12.11.2009, 18:48
Спасибо за помощь, дальше я уже допишу smile

Автор: GrayCardinal 12.11.2009, 19:03
mChief, 
Завсегда пожалуйста...

Автор: MAKCim 12.11.2009, 23:15
mChief, 
во-первых по самому коду, я настоятельно рекомендую компилировать с ключом -Wall и фиксить все warning'и
это просто хороший стиль, а иногда позволяет выявить потенциальне баги ;)

во-вторых по типу реализации сервера: никогда без особой необходиости не следует юзать форки
мультиплексирование ввода-вывода никто не отменял ;)

Автор: mChief 16.11.2009, 06:06
MAKCim,  спасибо за замечания
А можете немного пояснить про форки и мультиплексирование ввода-вывода ?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)