предоставляю тестовые исходники по проблеме,
чтотца что бы заоботало, а то ведь.. хех.. :/
Напомню: при записи в сокет — вываливается по таймауту ..
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*)¶m ) < 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;
}