сокеты (проблема с приемом/отправкой)
От: dr3  
Дата: 06.11.03 11:23
Оценка:
на клиенте:
ret = send(sFS, "PUT:filename", 13, 0); //посылаем команду PUT
...
//send size of file to file server
ret = send(sFS, "SIZE_PUT_FILE:31", 17, 0); //посылаем доп. информацию косаемо этой команды
if(ret == -1) perror("send");
//код возврта — не "-1" — т.е. отсылается
...


на сервере:
(с каждым новым клиентским запросом ассоциируется потокаовая функция
"childThread")

// the child thread
void *childThread(void *param) {

while(true) {

// handle data from a client
if ((nbytes = recv(childSocket, buf, sizeof(buf), 0)) <= 0) {
//вываливаемся...
}

//split the command we got
CommandSpliter c(buf); //спец. класс для парсинга команд

if(c.getCommandName() == "PUT") { // получили команду PUT

//обрабатываем команду PUT

if(ret = recv(childSocket, buf, sizeof(buf), 0) > 0) {
//всегда возвращает нуль и никого не ждет!!! <--------------????
}

}
}


вопрос: почему recv всегда возвращает ноль, и куда девается инфа от send?
Re: сокеты (проблема с приемом/отправкой)
От: Аноним  
Дата: 06.11.03 12:03
Оценка:
Здравствуйте, dr3, Вы писали:

dr3>вопрос: почему recv всегда возвращает ноль, и куда девается инфа от send?


Для WIN32 recv должна возвращвть 0 если соединение было закрыто.
Re[2]: сокеты (проблема с приемом/отправкой)
От: dr3  
Дата: 06.11.03 12:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, dr3, Вы писали:


dr3>>вопрос: почему recv всегда возвращает ноль, и куда девается инфа от send?


А>Для WIN32 recv должна возвращвть 0 если соединение было закрыто.


в луинуксе тоже.


еще заморочка:

на клиенте.
клиент отправляет файл на сервер:

//star sending file by bytes
int bytes=0;
int sizeBlock=1;
cout << "sending";
while( (fgets(buf, sizeBlock+1, pFile)) != NULL ) {
cout << ".";
ret = send(sFS, buf, sizeBlock+1 , 0);
if(ret=-1) perror("send");
}
cout << endl;


я думаю в этом и прична, того что recv возвращает нуль..


//
perror выбрасывает сообщение "send:illegal seek"
это уже не смешно


тот жа самый код прекрасно работет при пересылки данных с сервера на клиент

я начал по google лазить с "socket ilegall seek" — там намикают что это глюк библиотеки какаой то.

я юзаю ASPLinux7.3....
Re[3]: Разделяемые сегменты памяти
От: Murr Россия  
Дата: 11.11.03 08:27
Оценка:
Здравствуйте, dr3, Вы писали:

Кинь в форум вывод strace на твою программу ...
Re: сокеты (проблема с приемом/отправкой)
От: alexku Россия  
Дата: 11.11.03 09:31
Оценка:
Здравствуйте, dr3, Вы писали:

dr3>вопрос: почему recv всегда возвращает ноль, и куда девается инфа от send?


А ты волшебной функцией select пользуешься?
В твоём сокете просто может не быть данных в данный момент.

А вообще-то маловато кода, чтобы понять, что ты делаешь.
Re[2]: сокеты (проблема с приемом/отправкой)
От: dr3  
Дата: 12.11.03 08:36
Оценка:
Здравствуйте, alexku, Вы писали:

A>Здравствуйте, dr3, Вы писали:


dr3>>вопрос: почему recv всегда возвращает ноль, и куда девается инфа от send?


A>А ты волшебной функцией select пользуешься?

A>В твоём сокете просто может не быть данных в данный момент.

A>А вообще-то маловато кода, чтобы понять, что ты делаешь.



Очень даже может быть что дело в этом. Я чесно говоря не совсем понял логику работы seclect, хотя пытался ее втиснуть в код. Был бы благодарен если бы подсказали.

Итак напоминаю.
Есть сервер, есть клиен.
1 Клиент должет уметь получать(перекачать) файл с сервера
2 Клиент должет уметь отправить(закачать) файл на сервер
проблема в том что пункт 2 не выполняется, сообщения не доходят до сервера.

код:
сервер:

см. обработчик команды "PUT":

//CommandSpliter - класс - выделяет комманды закодированные в спец протокол обмена

/*
* fserver.cpp -- a fileServer
*/

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

#include <iostream>
#include <vector>
#include <string>
using namespace std;

#include "commandSpliter.h"

int PORT = 20001;  // port we're listening on

int listener;     // listening socket descriptor
int fdmax;

struct client_param {
 int socket;
 char* clientIP;
};

// the child thread
void *childThread(void *param) {

    char buf[1024];
    int nbytes;
    //
    struct client_param* p = (struct client_param*) param;
    int childSocket = p->socket;
    string clientIP = p->clientIP;
    
 while(true) {
    
        // handle data from a client
        if ((nbytes = recv(childSocket, buf, sizeof(buf), 0)) <= 0) {
    
            // got error or connection closed by client
            if (nbytes == 0) {
                // connection closed
                cout << "connection (" << clientIP << ")" << " was closed\n";
            } else {
                perror("recv");
            }
        
            close(childSocket); // bye!
            pthread_exit(0);
        }
    
        //printf("%s\n", buf);

        //split the command we got
        CommandSpliter c(buf);
    char strBuf[10];        
        
    if(c.getFrom()=="c") //from client?
    {
        command_attrs attrs;    
            
        //get - load from fserver to client it means
        if(c.getCommandName()=="GET") {
             FILE* pFile = NULL;
            
             attrs = c.getCommandAttrs();
             string fileName = attrs[0];
             string fileName2 = "file_store/" + fileName;
             pFile = fopen(fileName2.c_str(), "rt");
             int fSize=0;
             
             if(pFile != NULL) {
             
             //determinate size of file (in bytes)
             while( (fgets(strBuf, 2, pFile)) !=NULL ) fSize++;
             fseek(pFile, 0, SEEK_SET);
             //cout << "fSize:" << fSize << endl;
             
                cout << "client (" << clientIP <<  ") calling GET(" << fileName << ")" << endl; 
            cout << "sending";
            string command;
            command = "fs/SIZE_GET_FILE:";
            sprintf(strBuf, "%d", fSize);
            command += strBuf;
            int ret = send(childSocket, command.c_str(), command.length() + 1, 0);
            if(ret==-1) perror("send");                
            
            //start sending file by bytes
            int bytes=0;
            int sizeBlock=1;
            while( (fgets(strBuf, sizeBlock+1, pFile)) != NULL ) {
                cout << ".";
                send(childSocket, strBuf, sizeBlock+1 , 0);
            }
            cout << endl;
             }
             
             else
             {
                  cout << "The client(" << clientIP << ") FAILED to GETting file from FSERVER" << endl;
            int ret = send(childSocket, "fs/ERROR_GET_FILE", 19, 0);
            if(ret==-1) perror("send");
            continue;
             }
        } //if(c.getCommandName()=="GET")
        
        else
        
        if(c.getCommandName() == "DEL") {
        
            attrs = c.getCommandAttrs();
            string fileName = attrs[0];
            
            cout << "client (" << clientIP <<  ") call DEL(" << fileName << ")" << endl;  
            
            int ret = send(childSocket, "DELETED", 8, 0);
            perror("send");
            
        }//if(c.getCommandName() == "DEL") {
        
        else
        
        //put - load from client to file server it means
        if(c.getCommandName() == "PUT") {
        
            attrs = c.getCommandAttrs();
            string fileName = attrs[0];
            string fileName2 = "file_store/" + fileName;
            string fSize = attrs[1];
            
            cout << "client (" << clientIP <<  ") call PUT(" << fileName << "; size: " << fSize << ")" << endl;  
             //

            FILE* pFile = fopen(fileName2.c_str(), "w+t"); //create file
            if(pFile==NULL)  {
                    cout << "ERROR: could not create file, when file was putting" << endl;                 
                continue;
                }
            /*
             else {
                int ret = send(childSocket, "fs/ERROR_PUT_FILE", 19, 0);
                if(ret==-1) perror("send");
            }
            */
            
            //not work correcly yet
            /*
             int ret = recv(childSocket, buf, sizeof(buf), 0);
                 if(ret==0) {
                cout << "bad" << endl;
                fclose(pFile);
                 break;        
                 }
            */
            /*
             //getting body of file
             int cc=0;
             while( cc != atoi(fSize.c_str()) ) {
             
                 cout << "cc:" << cc << endl;
                             
                 int ret = recv(childSocket, buf, sizeof(buf), 0);
                 if(ret==0) {
                cout << "bad" << endl;
                fclose(pFile);
                 break;        
                 }
                
                fprintf(pFile, buf); //write in file here
                cc++;
             }
            */     
                              
             fclose(pFile);        
                
             cout << "The client (" << clientIP <<  ") saved file (" << fileName << ") on file server sucessfuly" << endl; 
                  
        }
                
    } //if(c.getFrom()=="c")
                
  } //while    
}

int main(int argc, char* args[])
{
    cout << "\nThe File Server starting..." << endl;
    
    if(argc > 1) {
       PORT = atoi(args[1]);
       if(PORT <= 0) {
        cout << "ERROR! The first argument must be the port number!" << endl;
        return -1;
       }
    }
        
    struct sockaddr_in myaddr;     // server address
    struct sockaddr_in remoteaddr; // client address
    int newfd;        // newly accept()ed socket descriptor
    int yes=1;        // for setsockopt() SO_REUSEADDR, below
    socklen_t addrlen;

    pthread_t cThread;

    // get the listener
    if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    // lose the pesky "address already in use" error message
    if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    // bind
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;
    myaddr.sin_port = htons(PORT);
    memset(&(myaddr.sin_zero), '\0', 8);
    if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        perror("bind");
        exit(1);
    }
    
    cout << "the File Server started and listening port " << PORT << endl;
    cout << "listening..." << endl;
    // listen
    if (listen(listener, 10) == -1) {
        perror("listen");
        exit(1);
    }

    // main loop
    while(true) {
        // handle new connections
        addrlen = sizeof(remoteaddr);
        if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) {
            perror("accept");
        } else {

        char* clientIP = inet_ntoa(remoteaddr.sin_addr);        
        
        //
        client_param param;
        param.clientIP = clientIP;
        param.socket = newfd;
            

            cout << "\n\nNew connection from "<< clientIP << " ip" << " on " << newfd << " socket;" << endl;                

        if (pthread_create(&cThread, NULL, childThread,  &param) <0) {
                perror("pthread_create");
                exit(1);
            }
        }

    }
    return 0;
}
Re[3]: Разделяемые сегменты памяти
От: Murr Россия  
Дата: 13.11.03 22:58
Оценка:
Здравствуйте, dr3, Вы писали:

Я бы посоветовал сделать вначале программы fwide(stderr, -1), чтобы не получать Illegal seek в самых неожиданных местах.
Re[3]: сокеты (проблема с приемом/отправкой)
От: alexku Россия  
Дата: 19.11.03 16:26
Оценка: 3 (1)
Извини, что долго не отвечал. Не было возможности.
Ты уже разобрался с селектом? Если да, то можешь не читать .

Я посмотрел твой код.
Что тебе нужно делать:
1. Использовать селект при каждом чтении и записи в сокет
2. Проверять возвращаемое функциями recv и send значение ВСЕГДА.

Селект останавливает выполнение процесса/потока до того момента, когда во входном буфере сокета появятся данные, готовые к употреблению или сокет, в который ты собираешься гнать данные, будет готов их принять. Иначе ты впустую тратишь время процессора на бесполезный цикл чтения/записи. Селект можно использовать не только с сокетами, а в принципе с любыми файловыми дескрипторами (по крайней мере с stdin точно можно, про остальное не уверен).
Я не буду повторять man, укажу только главное.

int select(номер_дескриптора_с_максимальным_значением + 1,/*!!!Не количество дескрипторов!!!*/
           набор_дескрипторов_для_чтения,/*0 если читать ничего не надо*/
           набор_дескрипторов_для_записи,/*0 если записывать ничего не надо*/
           набор_дескрипторов_для_исключений,/*ставь смело в 0*/
           время_ожидания)


В примере устанавливается на ожидание только один сокет и только на чтение или только на запись, но ты можешь установить их столько, сколько надо и на оба действия. Например, stdin можешь поставить на чтение, а сокет — на запись. Появились данные в stdin — прочитал, готов сокет — записал.

int socketReady(int s, int rw, int sec, int usec) {//rw = 0 - чтение, rw = 1 - запись
  struct timeval tv;
  fd_set rfds;
  fd_set wfds;
  fd_set *cfds;
  int res;

  FD_ZERO(&rfds); //читай man select
  FD_ZERO(&wfds);

  tv.tv_sec = sec;
  tv.tv_usec = usec;

  if(!rw) cfds = &rfds; //ожидаем сокет на чтение
  else    cfds = &wfds; //ожидаем сокет на запись

  FD_SET(s, cfds); //читай man select
  
  //обрати внимание на первый параметр.
  //!!!селект сбрасывает значения rfds и wfds, поэтому их надо устанавливать
  //перед каждым вызовом селект.
  res = select(s + 1, &rfds, &wfds, 0, &tv);
  if(res == -1) {
    // error
    return ERROR;
  } else if(!res) {
    // socket not ready, timeout expired
    return END_TIMEOUT;
  }
  //проверяем, готов ли нужный сокет
  if(FD_ISSET(s, cfds)) //читай man select
    return READY;
  else return ERROR;
}


и дальше

wile(1) {
  if(READY == (result = socketReady(s, 0, 10, 0))) { //читаем
    currRead = recv(s, readBuff, readBuffLen, 0);
    if(currRead = -1) {
      //ошибка, проверяем errno и вываливаемся из цикла или нет
    } else if(currRead == 0) {
      //тоже ненормально, значит сокет на том конце закрыт, вываливаемся из цикла
    } else {
      //работаем с тем, что получили,
      //количество полученного равно currRead
    }
  } else {
    //проверяем, что вернулось и т. д.
  }
}


и запись


wile(1) {
  if(READY == (result = socketReady(s, 1, 10, 0))) { //пишем
    sent = send(s, writeBuff, len, 0);
    if(sent = -1) {
      //ошибка, проверяем errno и вываливаемся из цикла или нет
    } else if(sent < len) {
      //записалось не всё, нужно будет дописывать то, что осталось в буфере
    } else {
      //готовим следующую порцию или заканчиваем
    }
  } else {
    //проверяем, что вернулось и т. д.
    //и вываливаемся из цикла, если надо
  }
}


И ещё несколько замечаний.
Нет никакого признака того, что из сокета прочитаны все данные. И то, что прочитано меньше, чем размер буфера, не говорит ни о чём. Нужно самостоятельно как-то уведомлять получателя о количестве отправленных данных или о том, что достигнут конец данных (какая-нибудь волшебная завершающая последовательность).
Если из сокета прочитано 0 байт, это значит то, он закрыт на другом конце, а не то, что в него отправлено 0 байт.
Сокет может быть закрыт на запись и открыт на чтение и наоборот. Смотри man 2 shutdown.
Если время ожидания вышло, это говорит только о том, что в читающем сокете до сих пор ничего нет или из пишущего сокета ничего не отправлено получателю (может он там просто забыл читать из сокета). Здесь надо самому принимать решение, что делать.
Re[4]: сокеты (проблема с приемом/отправкой)
От: dr3  
Дата: 24.11.03 12:12
Оценка:
Здравствуйте, alexku, Вы писали:

.. в теории должно было помочь, но..

короче пишу:
...
#include "sock_helper.h" //тут функция фенкция "socketReady"
...


//-----------------------------------------------------------------------------    
    //writing into socket (or sending)
    //socket ready?
    if(READY == (ret = socketReady(sDS, 1, 10, 0)))   //writing ...
    {
    int sent;
    int len; 
    
    while(true) { //write all from buffer
    
     len = command.length();
    
         sent = send (sDS, command.c_str(), len, 0);
     if(sent == -1) 
        throw new CommandException("command 'SAVE_FILE': sending FAILED!");
        
        //if had been wroten not all, then we need finish
        // writing from our buffer
        if(sent < len) {
            command = command.substr(sent-1, len-sent-1);
        //debug
        cout << "had been wroten not all.." << endl;
        continue;
        }
        
        //here everything from buffer was wroten. (it's OK)
        break;
    }
     
    } else { //SOCKET NOT READY
    //cheking 'ret'
    if(ret == ERROR)
        throw new CommandException("command 'SAVE_FILE': ERROR!");
    if(ret == END_TIMEOUT)
        throw new CommandException("command 'SAVE_FILE': END_TIMEOUT!");
    }  
//-----------------------------------------------------------------------------   

...



Получается, что сокет всегда занят и до "send" дело не доходит никогда.

Хотя без функции ожидания, в данном случае, данные посылаются норамально.Т.е. на другом конце есть кому читать.


Пасиба!
Re[4]: сокеты (проблема с приемом/отправкой) [тестовые исход
От: dr3  
Дата: 24.11.03 18:14
Оценка:
предоставляю тестовые исходники по проблеме,
чтотца что бы заоботало, а то ведь.. хех.. :/


Напомню: при записи в сокет — вываливается по таймауту ..
test_client.cpp
#include "sock_helper.h"
#include <string>

using namespace std;

int main() {

    //yep, it's my local ip
    string HOST_IP = "192.168.1.66";
    int SERVER_PORT = 5432;
    int s;
    struct sockaddr_in sin;

    // active open
        if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
            perror("socket");
            exit(1);
    }
    
    // build address data structure 
        bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;
        sin.sin_addr.s_addr  = inet_addr(HOST_IP.c_str());
        sin.sin_port = htons (SERVER_PORT);

        //connecting...    
    if( connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0 ) {
            close(s);
            cout << "COMMUNICATION ERROR: could not connect to the test server!\nTry again or type ctrl-c for exit.\n";
    }

    //This is our command with '@'-mark as end of command string
    string command = "USR@";
    
    int ret;

    //writing into the socket (or sending)
    //is socket ready?
    if( READY == ( ret = socketReady(s, 1, 2, 0) ) )   //writing ...
    {
    int sent;
    int len;                           
    
    cout << "command:" << command << endl;
    
    while(true) { //write all from buffer
    
     cout << "bla-bla" << endl;        
    
     len = command.length();
    
         sent = send (s, command.c_str(), len, 0);
     
     cout << "sent:" << sent << endl;
     
     if(sent == -1) 
        cout << "command 'USR': sending FAILED!";
        
        //if had been wroten not all, then we need finish
        // writing from our buffer
        if(sent < len) {
            command = command.substr(sent - 1, len - sent - 1);
        //debug
        cout << "had been wroten not all.." << endl;
        continue;
        }
        
        //here everything from buffer was wroten. (it's OK)
        break;
    }
    
     } //IF NOT READY
     
     else
     {
         //cheking 'ret'
    if(ret == ERROR) {
        cout << "ERROR!" << endl;
        cout << "command 'USR': ERROR!";
    }
    if(ret == END_TIMEOUT) {
        cout << "END_TIME_OUT" << endl;
        cout << "command 'USR': END_TIME_OUT";        
    }
     }
     
 return 0;
}


//----------------


test_server.cpp
/*
* test_server.cpp -- a test server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "sock_helper.h"

#include <iostream>
#include <string>
using namespace std;

#define PORT 5432  // port we're listening on

//Structure to use as parameter for child-thread function
struct thread_param {
  char* IP;
  int s;
};

// the child thread
void* childThread(void *_param) {

    char buf[1024];
    int nbytes;
    struct thread_param* param = (struct thread_param*)_param;
    string ip = param->IP;
    int sClient = param->s; 
    
    cout << "we have got new connection from " << ip << endl;
    
    int ret;
    int currentRead;
    
    while(true) { //the main recive-loop
    
    string cmdString = "";    
    
    while(true) //while not read whole command
    {
      //is socket ready?
      if(READY == (ret = socketReady(sClient, 0, 10, 0))) 
      { //reading
        
        currentRead = recv(sClient, buf, sizeof(buf), 0);
        if(currentRead == -1) {
        perror("recv");
        close(sClient); // bye!
            pthread_exit(0);
        } else
        if(currentRead == 0) { 
        // the connection was closed by client
        cout << "the connection was closed by client" << endl;        
        close(sClient); // bye!
            pthread_exit(0);
        } else
        { 
        //work with that we got
        cmdString += buf;
        char end = cmdString.c_str()[cmdString.length() - 1];
        cout << "we got1: " << cmdString << endl;    
        if(end == '@') //end byte of command? - break from local 'while'
        {
            int index = cmdString.find_first_of("@");
            cmdString = cmdString.substr(0, index); //without end point
            break;
        }
        else continue;
        }
        
      }  else { //SOCKET NOT READY
        //cheking 'ret'
        if(ret == ERROR) {
            cout << "recive ERROR!" << endl;
            close(sClient); // bye!
                pthread_exit(0);
        }
        if(ret == END_TIMEOUT) {
                cout << "recive END_TIMEOUT!" << endl;
                close(sClient); // bye!
                pthread_exit(0);
        }
      }
    } //end of local while  

    //analys of recived data    
    if(cmdString == "USR") {
        cout << "We got 'usr'" << endl;
    }
    
      } //the main recive-loop
}


int main(void) {

    struct sockaddr_in myaddr;     // server address
    struct sockaddr_in remoteaddr; // client address
    int _sClient;                // newly accept()ed socket descriptor
    int _sServer;
    socklen_t addrlen;
    pthread_t cThread;
    struct thread_param param;       //param for child thread function    
        
    cout << "\nStarting test server...." << endl;

    // get the listener
    if ((_sServer = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    // lose the pesky "address already in use" error message
    int yes=1;
    if (setsockopt(_sServer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    // bind
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;
    myaddr.sin_port = htons(PORT);
    memset(&(myaddr.sin_zero), '\0', 8);
    if (bind(_sServer, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    cout << "the test server started." << endl;
    cout << "listening..." << endl;
    // listen
    if (listen(_sServer, 10) == -1) {
        perror("listen");
        exit(1);
    }

    // main loop
    while(true) {
    
        // handle new connections
        addrlen = sizeof(remoteaddr);
        if ((_sClient = accept(_sServer, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) {
            perror("accept");
        } else {
    
        struct thread_param param;
        param.IP = inet_ntoa(remoteaddr.sin_addr);
        param.s  = _sClient; 
        
        if ( pthread_create(&cThread, NULL, childThread, (void*)&param ) < 0) {
                perror("pthread_create");
                exit(1);
            }
        }

    }
    
    return 0;
}



sock_helper.h


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

#define READY 0
#define ERROR  -1
#define END_TIMEOUT -2

#include <iostream>
using namespace std;

/**
*parameters:
* s - descriptor (number of descriptors with max values)
* rw = 0 - reading, rw = 0 - writing
*/
int socketReady(int s, int rw, int sec, int usec) {

 struct timeval tv;
 fd_set rfds;
 fd_set wfds;
 fd_set *cfds;
 int res;
 
 FD_ZERO(&rfds); //read man for 'select'
 FD_ZERO(&wfds); // --//--
 
 tv.tv_sec = sec;
 tv.tv_usec = usec;
 
 if(!rw) cfds = &rfds; //waiting socket for reading
   else cfds = &rfds;  //waiting socket for writing
 
 FD_SET(s, cfds); //read man for 'select'
 
 //pay attantion for first paramater.
 //select resets both 'rfds' and 'wfds' parameters, threfor we must set its
 //before each invoking of select 
 res = select(s + 1, &rfds, &wfds, 0, &tv);
 
 //debug:
 cout << "res:" << res << endl;
 
 if(res == -1) {
    //error
    return ERROR;
 } else if(!res) {
    // socket not ready, timeout expired
    return END_TIMEOUT;
 }
 //chek whether ready 'our' socket
 if(FD_ISSET(s, cfds)) //read man for 'select'
    return READY;
 else return ERROR;
}
Re[5]: сокеты (проблема с приемом/отправкой) [тестовые исход
От: GarikTot  
Дата: 28.11.03 16:20
Оценка:
dr3>sock_helper.h


dr3>
 
dr3> if(!rw) cfds = &rfds; //waiting socket for reading
dr3>   else cfds = &rfds;  //waiting socket for writing
//судя по всему здесь должно быть wfds
 
dr3>
Re[6]: сокеты (проблема с приемом/отправкой) [тестовые исход
От: GarikTot  
Дата: 28.11.03 16:27
Оценка:
Здравствуйте, GarikTot, Вы писали:

И еще (возможно немного не втему):
раз уж пишешь на плюсах — полезно написать иерархию классов:

Socket
/ \
StreamSocket DatagramSocket
/ \
Server Client

и т. д. и т. п.

Один раз отладишь — и использую потом везде
И кодтакой читать и отлаживать легче намного

Все сказанное — ИМХО, конечно же

Удачи
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.