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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.