LINUX.ORG.RU

Клиент-Сервер Socket linux (Система обмена сообщениями)

 , , ,


2

3

Здравствуйте! Помогите,пожалуйста,доработать Клиент-Сервер.Никак не получается... Завтра последний день сдачи Условия выполнения: «Задание: разработать приложение-клиент и приложение сервер, обеспечивающие функции мгновенного обмена сообщений между пользователями.

Основные возможности. Серверное приложение должно реализовывать следующие функции: 1) Прослушивание определенного порта 2) Обработка запросов на подключение по этому порту от клиентов 3) Поддержка одновременной работы нескольких клиентов через механизм нитей 4) Передача текстового сообщения одному клиенту 5) Передача текстового сообщения всем клиентам 6) Прием и ретрансляция входящих сообщений от клиентов 7) Обработка запроса на отключение клиента 8) Принудительное отключение указанного клиента

Клиентское приложение должно реализовывать следующие функции: 1) Установление соединения с сервером 2) Передача сообщения всем клиентам 3) Передача сообщения указанному клиенту 4) Прием сообщения от сервера с последующей индикацией 5) Разрыв соединения 6) Обработка ситуации отключения клиента сервером

Настройки приложений. Разработанное клиентское приложение должно предоставлять пользователю настройку IP-адреса или доменного имени сервера сообщений и номера порта сервера. »

Пока в работе у меня выполнено следующие условия:Сервер:1,2,3 ;Клиент:1,. В данном случае у меня клиент отправляет сообщение серверу,а сервер отправляет этоже сообщение обратно клиенту.

Код Сервера:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
    int sock, listener;       // дескрипторы сокетов
    struct sockaddr_in addr; // структура с адресом
    char buf[2048];       // буфур для приема
    int bytes_read;           // кол-во принятых байт
 
 
    listener = socket(AF_INET, SOCK_STREAM, 0); // создаем сокет для входных подключений
    if(listener < 0)
    {
        perror("socket");
        exit(1);
    }
    
    // Указываем параметры сервера
    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    //addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) // связываемся с сетевым устройство. Сейчас это устройство lo - "петля", которое используется для отладки сетевых приложений
    {
        perror("bind");
        exit(2);
    }
 
    listen(listener, 1); // очередь входных подключений
    
    while(1)
    {
        sock = accept(listener, NULL, NULL); // принимаем входные подключение и создаем отделный сокет для каждого нового подключившегося клиента
        if(sock < 0)
        {
            perror("Прием входящих подключений");
            exit(3);
        }
 
switch(fork())
{
case -1:
 perror("fork");
 break;
case 0:
close(listener);
 
 
        while(1)
        {
            printf("Ожидаем сообщение...\n");
 
 
            bytes_read = recv(sock, buf, 2048, 0); // принимаем сообщение от клиента
            if(bytes_read <= 0) break;
            printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf);
            printf("Отправляю принятое сообщение клиенту\n");
            send(sock, buf, bytes_read, 0); // отправляем принятое сообщение клиенту
        }
    
        close(sock); // закрываем сокет
        _exit(0);
default:
close(sock);
}   
    }
    
    return 0;
}
Код Клиента:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
 
int main (int argc, char **argv)
{
char message[2048];//=(char*)malloc(sizeof(char));// сообщение на передачу
char buf[sizeof(message)];
int port,ch;
//----------------------------------------------------------------------------
if(argc!=3){
printf("Не верное кол-во аргументов!\nДолжно быть 2 аргумента (Порт,ip-адрес -сервера)!\n");
exit(0);
}
 
    int sock;                 // дескриптор сокета
    struct sockaddr_in addr; // структура с адресом
    struct hostent* hostinfo;
port = atoi(argv[1]);
hostinfo = argv[2];
    sock = socket(AF_INET, SOCK_STREAM, 0); // создание TCP-сокета
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }
 
    // Указываем параметры сервера
    addr.sin_family = AF_INET; // домены Internet
    addr.sin_port = htons(port); // или любой другой порт...
    addr.sin_addr.s_addr=inet_addr(hostinfo);
    /*
     * Начинающие программисты часто спрашивают, как можно отлаживать сетевую программу, если под рукой нет сети.
     * Оказывается, можно обойтись и без неё. Достаточно запустить клиента и сервера на одной машине, а затем использовать для соединения адрес интерфейса внутренней петли (loopback interface).
     * В программе ему соответствует константа INADDR_LOOPBACK (не забудьте применять к ней функцию htonl!).
     * Пакеты, направляемые по этому адресу, в сеть не попадают.
     * Вместо этого они передаются стеку протоколов TCP/IP как только что принятые.
     * Таким образом моделируется наличие виртуальной сети, в которой вы можете отлаживать ваши сетевые приложения.
     */
   // addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
      //addr.sin_addr.s_addr = inet_addr(host_ip);
 if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) // установка соединения с сервером
    {
        perror("Подключение");
        exit(2);
    }
 
while(1){//WHILE <---
//----------------------------------------------------------------------------
    printf("Введите сообщение серверу(Для выхода:exit): "); 
    if (!strcmp(gets(message), "exit")){close(sock);return 0;}
//----------------------------------------------------------------------------
 
    printf("отправка сообщения на сервер...\n");
    send(sock, message, sizeof(message), 0); // отправка сообщения на сервер
    int bytes_read = 0;
    printf("Ожидание сообщения\n");
    bytes_read = recv(sock, buf, sizeof(message), 0);
    printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf); // прием сообщения от сервера
    
 
}//END_WHILE
    
return 0;
    
}

switch(fork())

fork() и указанные в ТЗ нити - мягко говоря разные вещи

и перед тем как начать списывать код из источников стоит набросать на бумажке протокол: какие и как данные ходят туда-сюда, форматы сообщений, состояния соединений.

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

fork() и указанные в ТЗ нити - мягко говоря разные вещи

А разве и то и другое не через clone() выполняется?

i-rinat ★★★★★ ()
Ответ на: комментарий от vonenij

Еще вопросик:

Как сделать так,чтобы клиент мог скачать с сервера песню?Например формата .mp3

BladzheR ()
Ответ на: Еще вопросик: от BladzheR

А у тебя по этому поводу свои мысли есть какие-нибудь? Мне просто интересно, есть ли у тебя мозг впринципе.

grouzen ★★ ()
Ответ на: Еще вопросик: от BladzheR

есть куча протоколов прикладного уровня... самое простое читать в стрим файл и send()/recv()

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

Возможно как то так: На сервере как то так: FILE * file; file = fopen(«test.mp3»,«wt»); после делаю send... Далее на клиента пишу recv ... а вот дальше не знаю,куда записать эту песню и т.д.

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

Далее на клиента пишу recv ... а вот дальше не знаю,куда записать эту песню и т.д.

Также открываешь файл на запись и пишешь.

vonenij ()
Ответ на: комментарий от BladzheR

Нет, не хочу тратить время. Читай man'ы.

Ты делаешь recv из сокета в буфер, а потом write (man 2 write) из буфера в файл

vonenij ()
Ответ на: комментарий от BladzheR
//======================================================
#define BUF_SIZE 4096 

FILE* f = fopen("filename_in.mp3","rb");

fseek (f , 0 , SEEK_END);
fSize = ftell (f);
rewind (f);

long sended = 0;
long readed = 0;

char buffer[BUF_SIZE];

{
 readed = fread (buffer,1,BUF_SIZE,f);
 send(sock, buffer, readed, 0);
 sended += readed; 

}while(sended <= fSize));

fclose(f);
close(sock);

//======================================================

#define BUF_SIZE 4096;

FILE* f = fopen("filename_out.mp3","wb");

char buffer[BUF_SIZE];
long rcv_len = 0;

{

 rcv_len = recv(sock, buffer, BUF_SIZE, 0);
 fwrite (buffer,1,rcv_len,f);

}while(rcv_len != 0);

close(sock);
fclose(f);

писал прям тут, думаю суть понятна

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

есть опечатки сразу сам вижу.. но чет редактирование поста не доступно

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

Спасибо!

Пару опечаток исправил,но не компилируется... gcc пишет:expected declaration of statement at and of intut.

Код: FILE* f = fopen(«music.mp3»,«rb»);

fseek (f , 0 , SEEK_END); int fsize = ftell (f); rewind (f);

long sended = 0; long readed = 0;

char buffer[BUF_SIZE];

do{ readed = fread (buffer,1,BUF_SIZE,f); send(sock, buffer, readed, 0); sended += readed;

}while(sended <= fsize);

fclose(f); close(sock);

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

Спасибо!

Пару опечаток исправил,но не компилируется... gcc пишет:expected declaration of statement at and of intut.

Код:

FILE* f = fopen("music.mp3","rb");

fseek (f , 0 , SEEK_END);
int fsize = ftell (f);
rewind (f);

long sended = 0;
long readed = 0;

char buffer[BUF_SIZE];

do{
 readed = fread (buffer,1,BUF_SIZE,f);
 send(sock, buffer, readed, 0);
 sended += readed; 

}while(sended <= fsize);

fclose(f);
close(sock);

BladzheR ()
Ответ на: комментарий от jo_b1ack

jo_b1ack,Спасибо тебе большое!!! Теперь дошло как это работает.

Осталось разбираться с системой обмена сообщений...

BladzheR ()
Ответ на: комментарий от jo_b1ack

Мог ли бы еще помочь в одной проблемке?

У меня все передаётся,но после сервер и клиент просто висят...

Если я убираю while то передается только 4кб и идет дальше по коду т.е. не висит ...

Как это исправить?

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

попробуй заменить в приеме строчку

while(rcv_len != 0);

на while(rcv_len > 0);

возможно после закрытия сокета recv возвращает не 0 - закрытие соединения, а SOCKET_ERROR

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

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

Листинг клиента:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define BUF_SIZE 4096
int main (int argc, char **argv)
{
char message[2048];//=(char*)malloc(sizeof(char));// сообщение на передачу
char buf[sizeof(message)];
int port,ch;
//----------------------------------------------------------------------------
if(argc!=3){
printf("Не верное кол-во аргументов!\nДолжно быть 2 аргумента (Порт,ip-адрес -сервера)!\n");
exit(0);
}

    int sock;				  // дескриптор сокета
    struct sockaddr_in addr; // структура с адресом
    struct hostent* hostinfo;
port = atoi(argv[1]);
hostinfo = argv[2];
    sock = socket(AF_INET, SOCK_STREAM, 0); // создание TCP-сокета
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

	// Указываем параметры сервера
    addr.sin_family = AF_INET; // домены Internet
    addr.sin_port = htons(port); // или любой другой порт...
    addr.sin_addr.s_addr=inet_addr(hostinfo);
    /*
     * Начинающие программисты часто спрашивают, как можно отлаживать сетевую программу, если под рукой нет сети.
     * Оказывается, можно обойтись и без неё. Достаточно запустить клиента и сервера на одной машине, а затем использовать для соединения адрес интерфейса внутренней петли (loopback interface).
     * В программе ему соответствует константа INADDR_LOOPBACK (не забудьте применять к ней функцию htonl!).
     * Пакеты, направляемые по этому адресу, в сеть не попадают.
     * Вместо этого они передаются стеку протоколов TCP/IP как только что принятые.
     * Таким образом моделируется наличие виртуальной сети, в которой вы можете отлаживать ваши сетевые приложения.
     */
   // addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
      //addr.sin_addr.s_addr = inet_addr(host_ip);
 if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) // установка соединения с сервером
    {
        perror("Подключение");
        exit(2);
    }
while(1){
int counter=0;
char buftext[1024];
while(counter!=1){
int bytes_read=recv(sock,buftext,1024,0);
printf("Принятое сообщение от сервера: %s/n",buftext);

printf("Введите номер композиции(Для выхода:exit): "); 
    if (!strcmp(gets(message), "exit")){close(sock);return 0;}
send(sock, message, sizeof(message), 0); // отправка сообщения на сервер
counter=1;
}
if(counter==1){

FILE* f = fopen("music.mp3","wb");

char buffer[BUF_SIZE];
long rcv_len = 0;
time_t seconds;
time_t seconds1;
seconds=time(NULL);
do{

 rcv_len = recv(sock, buffer, BUF_SIZE, 0);
 fwrite (buffer,1,rcv_len,f);
//seconds1=time(NULL);
//seconds1=seconds1-seconds;
//if(seconds1 >10){break;}
}while(rcv_len > 0);

//close(sock);
fclose(f);
}
}close(sock);
/*
while(1){//WHILE <---
//----------------------------------------------------------------------------
    printf("Введите сообщение серверу(Для выхода:exit): "); 
    if (!strcmp(gets(message), "exit")){close(sock);return 0;}
//----------------------------------------------------------------------------

	printf("отправка сообщения на сервер...\n");
    send(sock, message, sizeof(message), 0); // отправка сообщения на сервер
    int bytes_read = 0;
    printf("Ожидание сообщения\n");
    bytes_read = recv(sock, buf, sizeof(message), 0);
    printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf); // прием сообщения от сервера
    

}//END_WHILE
    */
return 0;
    
}
Листинг сервера
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUF_SIZE 4096
int main()
{
    int sock, listener; 	  // дескрипторы сокетов
    struct sockaddr_in addr; // структура с адресом
    char buf[2048];		  // буфур для приема
    int bytes_read;			  // кол-во принятых байт


    listener = socket(AF_INET, SOCK_STREAM, 0); // создаем сокет для входных подключений
    if(listener < 0)
    {
        perror("socket");
        exit(1);
    }
    
    // Указываем параметры сервера
    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    //addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) // связываемся с сетевым устройство. Сейчас это устройство lo - "петля", которое используется для отладки сетевых приложений
    {
        perror("bind");
        exit(2);
    }

    listen(listener, 1); // очередь входных подключений
    
    while(1)
    {
        sock = accept(listener, NULL, NULL); // принимаем входные подключение и создаем отделный сокет для каждого нового подключившегося клиента
        if(sock < 0)
        {
            perror("Прием входящих подключений");
            exit(3);
        }
while(1){
int counter=0;
while(counter!=1){
char text[]="Привет,Я музыкальный сервис!Вот мои композиции:";
char buftext[sizeof(text)];
send(sock,text,sizeof(text),0);
bytes_read = recv(sock, buf, 2048, 0); // принимаем сообщение от клиента
            if(bytes_read <= 0) break;
            printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf);
counter=1;
}

FILE* f;
int x=atoi(buf);
if(counter==1){

switch(x){
case 1:
f = fopen("1.mp3","rb");
break;
case 2:
f = fopen("2.mp3","rb");
break;
case 3:
f = fopen("3.mp3","rb");
break;
case 4:
f = fopen("4.mp3","rb");
break;
case 5:
f = fopen("5.mp3","rb");
break;
case 6:
f = fopen("6.mp3","rb");
break;
}
fseek (f , 0 , SEEK_END);
int fsize = ftell (f);
rewind (f);

long sended = 0;
long readed = 0;

char buffer[BUF_SIZE];
time_t seconds;
time_t seconds1;
seconds=time(NULL);
do{
 readed = fread (buffer,1,BUF_SIZE,f);
 send(sock, buffer, readed, 0);
 sended += readed; 
//seconds1=time(NULL);
//seconds1=seconds1-seconds;
//if(seconds1 >10){break;}
}while(sended <= fsize);

fclose(f);

}
}

/*int filefd=0,servfd=0;
size_t nbytes=0;
size_t filesize=0;
char recvbuf[BUFSIZE];
if((filefd=open("file.mp3",rb))==-1){printf(open file error);exit(4);}
filesize = (size_t)lseek(filefd,0,SEEK_END);
lseek(filefd,0,0);

if(sendfile(sock,filefd,NULL,filesize) != filesize){
perror("fail to send file");close(filefd);close(sock);
}

while(recv(servfd,recvbuf,BUFSIZE,0)>0){fputs(recvbuf,stdout);}*/
/*
switch(fork())
{
case -1:
 perror("fork");
 break;
case 0:
close(listener);


        while(1)
        {
			printf("Ожидаем сообщение...\n");


            bytes_read = recv(sock, buf, 2048, 0); // принимаем сообщение от клиента
            if(bytes_read <= 0) break;
            printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf);
            printf("Отправляю принятое сообщение клиенту\n");
            send(sock, buf, bytes_read, 0); // отправляем принятое сообщение клиенту
        }
    
        close(sock); // закрываем сокет
        _exit(0);
default:
close(sock);
}  */ 
    }
    close(sock);
    return 0;
}

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

у тебя в сервере 2 бесконечных цикла, и close(sock); после них.. ясное дело оно висит... бесконечные циклы это вообще зло...

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

К сожалению ,все равно висит... Убрал все while того где идет передача файла в сервере и клиенте

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

у тебя цикл начинается прям перед accept... поставь close(sock) после fclose(f); вприеме файла на сервере

jo_b1ack ★★★★ ()

Убиваем ваш сервер. Нужно на сервере проверку ограничение на количество соединений поставить.

 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
 
int main (int argc, char **argv)
{
char message[2048]="hello\n";//=(char*)malloc(sizeof(char));// сообщение на передачу
char buf[sizeof(message)];
int port,ch;
//----------------------------------------------------------------------------
if(argc!=3){
printf("Не верное кол-во аргументов!\nДолжно быть 2 аргумента (Порт,ip-адрес -сервера)!\n");
exit(0);
}
 
    int sock;                 // дескриптор сокета
    struct sockaddr_in addr; // структура с адресом
    struct hostent* hostinfo;
port = atoi(argv[1]);
hostinfo = argv[2];
    sock = socket(AF_INET, SOCK_STREAM, 0); // создание TCP-сокета
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }
 
    // Указываем параметры сервера
    addr.sin_family = AF_INET; // домены Internet
    addr.sin_port = htons(port); // или любой другой порт...
    addr.sin_addr.s_addr=inet_addr(hostinfo);
    /*
     * Начинающие программисты часто спрашивают, как можно отлаживать сетевую программу, если под рукой нет сети.
     * Оказывается, можно обойтись и без неё. Достаточно запустить клиента и сервера на одной машине, а затем использовать для соединения адрес интерфейса внутренней петли (loopback interface).
     * В программе ему соответствует константа INADDR_LOOPBACK (не забудьте применять к ней функцию htonl!).
     * Пакеты, направляемые по этому адресу, в сеть не попадают.
     * Вместо этого они передаются стеку протоколов TCP/IP как только что принятые.
     * Таким образом моделируется наличие виртуальной сети, в которой вы можете отлаживать ваши сетевые приложения.
     */
   // addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
      //addr.sin_addr.s_addr = inet_addr(host_ip);
 if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) // установка соединения с сервером
    {
        perror("Подключение");
        exit(2);
    }
long long int message_counter=0;
while(1){//WHILE <---
//----------------------------------------------------------------------------
    printf("Введите сообщение серверу(Для выхода:exit): "); 
    //if (!strcmp(gets(message), "exit")){close(sock);return 0;}
//----------------------------------------------------------------------------
 
    printf("отправка сообщения на сервер...\n");
    send(sock, message, sizeof(message), 0); // отправка сообщения на сервер
    int bytes_read = 0;
    printf("Ожидание сообщения\n");
    bytes_read = recv(sock, buf, sizeof(message), 0);
    printf("Получено %d bytes\tСообщение: %s\n", bytes_read, buf); // прием сообщения от сервера
    printf("Переданно на сервер [%lld] сообщений\n", ++message_counter);
 
}//END_WHILE
    
return 0;
    
}
Dron ★★★★★ ()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от Dron

да там куча и маленькая тележка косяков.. в этом коде

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

Здравствуйте! Тоже начал писать сервер и клиент на чистом С, вы могли бы указать косяки, желательно куски проблемного кода, очень интересно. И немного оффтоп вопрос, в двух словах, какие есть пути импрува сервера/клиента ? Какие фичи еще допилить можно ? Пока есть идея сделать простой клиент/сервер и сниффер, который будет парсить передаваемые пакеты, также есть мысль добавить шифрование траффика и потом попытаться заточить под это свой сниффер. Естественно я нацелен писать велосипеды, ради изучения как языка С, так и сетевого программирования.

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

пиши и выкладывай на форум) думаю, обосрать тут все горазды что угодно ;-)

jo_b1ack ★★★★ ()

Чат

Доброго времени суток. Подскажите, вы реализовали все задачи, которые перед вами стояли в этой теме? Не могли бы поделиться данной системой передачи сообщений? Спасибо.

anonymous ()
Ответ на: Чат от anonymous

Что, уже сессия началась?

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

Еще нет, а вот курсовые уже нужно сдавать. Может кто-нибудь сможет помочь или подтолкнуть в нужное русло. Вообщем задача поставлена так: «Сетевой чат (TCP)fork()»

Столкнулся вот с такой проблемой: Отправка, прием, обратная отправка сообщений - все реализовано. Для каждого клиента создается новый процесс и создается массив сокетов подключенных к серверу, который обрабатывается в этом процессе и отправляет данные всем имеющимся в массиве клиентам. При еще одном подключении, опять создается новый процесс, обновяется массив сокетов и т.д. Но у первого клиента массив сокетов не обновляется по понятным причинам. т.е. он работает со старой версией массива сокетов и не видит новых клиентов, которые подключились после него. Допустим подключено 3 клиента. Если сообщение отправит первый клиент, то сервер отправит сообщение только ему. т.к. у него в массиве хранится только он сам. Если отправит второй клиент сообщение, то сервер отправит обратно уже первому и второму клиенту. Если отправит третий клиент сообщение, то сервер обработает отправку и в первый и во второй и в третий клиент, т.к. он содержит в массиве все подключенные клиенты. Пробовал записывать в файл всех новых клиентов, и при обработке запроса, он считывает с файла сокеты и соответственно отправляет всем. Но тоже ничего не выходит. Считывать - считывает, но сообщения не доходят до клиента.

Есть решение этой проблемы? Спасибо.

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

А клиенты должны именно через выданный сокет работать? Т.е. все на одной машине? Как конкретно звучит задачка?

В твоей формулировке можно сделать так:
Завести shared memory и в ней хранить массив сокетов. Естественно размер массива задан статически. И стоит серелиазовать доступ к массиву (например мютексом).
Или использовать PF_UNIX сокеты и хранить их в определенном месте на диске.

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

В задаче ничего про сокеты не сказано. А сформулирована задача следующим образом. Реализовать клиент-сервер программу для передачи сообщений. Использовать TCP протокол и fork().

Т.е. реализовать чат один ко многим через TCP и fork. Будет огромным плюсом, если добавить приватный чат (один к одному)

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

Спасибо за подсказку. Надо попробовать с разделяемой памятью. А почему не работает обычное сохранение сокетов в файл? Ведь файл все время обновляется, сервер имеет к нему доступ, там хранятся все подключенные клиенты. Но вот сообщение не отправляет на клиенты, которые были подключены после клиента, который отправляет сообщение.

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

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

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

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

Как я понимаю, у каждого процесса есть свой порт, его и надо использовать. Он узнается с помощью getpid(); После вызова форка, я записываю порт в файл, вызывается функция где должно рассылаться наше сообщение. Там я считываю все порты, а что с ними делать дальше? Как прикрутить к рассылке. Я отправляю функцией sendto, где в параметрах указывается (номер сокета,сообщение, размер сообщения и т.д.) Вот раньше я сохранял номера сокетов и спокойно отправлял, но с известной проблемой. А что делать с портом? Как его прикрутить к отправке сообщений? Спасибо.

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

Вот класический пример tcp клиент/сервера

Тут два разных процесса идет: создание серверного сокета для приема соединений. И создание сокета, для соединения с сервером. В твоем случае можно основной процесс сделать в виде сервера, а дочерние - подключенными к нему клиентами.

Запись и чтение можно делать при помощи read/write.
getpid возвращает пид процесса, с номером порта не связанно.

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