C++로 소켓을 만들었는데 특정 연결 시간 초과가 필요했습니다. 그래서 무슨 일이 일어나고 있는지의 :소켓 읽기 : EAGAIN : 리소스를 일시적으로 사용할 수 없습니다.
- 그것이 NON_BLOCKING 확인 소켓을 작성
- 전화 연결
- 그것은 -1을 반환하고
- 이 전화
- 반품> 0을 선택 예상대로의 errno EINPROGRESS, 그래서 연결되었습니다
- 소켓을 다시 블로킹하십시오.
bool mastControl::prepareSocket(char * address, int port, int * sockfd) {
struct sockaddr_in serv_addr;
struct timeval timeout = {0,100000};
struct timeval connTimeout;
struct hostent * server = NULL;
fd_set socketSet;
socklen_t lon;
int sockOpt = 0;
long socketFlags = 0;
int buffersize = 8;
int res = 0;
int connectReturn = 0;
const int WAIT_TO_RECONN = 15;
server = gethostbyname(address);
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (*sockfd < 0) {
qDebug()<<"Impossible to open socket: "<<strerror(errno);
return false;
}
if (server == NULL) {
qDebug()<<"No such host: "<<strerror(h_errno);
return false;
}
// Initializating server direction struct:
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(port);
// Making socked non-blocking in order to set a timeout value for connection:
if((socketFlags = fcntl(*sockfd, F_GETFL, NULL)) < 0){
qDebug()<<"Impossible to retrieve sockets descriptor flags "<<strerror(errno);
return false;
}
socketFlags |= O_NONBLOCK;
if(fcntl(*sockfd, F_SETFL, socketFlags) <0){
qDebug()<<"Impossible to update sockets descriptor flags: "<<strerror(errno);
return false;
}
connectReturn = connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
if(connectReturn < 0){
if(errno == EINPROGRESS){
do{
// Establishing a 15 seconds timeout:
connTimeout.tv_sec = 15;
connTimeout.tv_usec = 0;
FD_ZERO(&socketSet); // Initialising set of sockets as an empty set
FD_SET(*sockfd, &socketSet); // Adding socket to set
connectReturn = select(*sockfd+1, NULL, &socketSet, NULL, &connTimeout);
if(connectReturn<0 && errno!=EINTR){ // Error in select
qDebug()<<"Connection error in select function: "<<strerror(errno);
return false;
}
else if(connectReturn>0){ // Socket selected for writing
lon = sizeof(int);
if(getsockopt(*sockfd, SOL_SOCKET, SO_ERROR, (void*)(&sockOpt), &lon) <0){
qDebug()<<"Unnable to get socket options: "<<strerror(errno);
return false;
}
// Checking the value returned:
if(sockOpt){
qDebug()<<"Error in delayed connection: "<<strerror(errno);
return false;
}
break;
}
else{ // Timeout
qDebug()<<"Connection timeout exceeded: "<<strerror(errno);
return false;
}
} while (1);
}
else{
qDebug()<<"Connection error: "<<strerror(errno);
sleep(WAIT_TO_RECONN); // Wait 15 seconds
return false;
}
}
//Connected
// Must set the socket as blocking again:
if((socketFlags = fcntl(*sockfd, F_GETFL, NULL)) < 0){
qDebug()<<"Impossible to retrieve sockets descriptor flags "<<strerror(errno);
return false;
}
socketFlags &= (~O_NONBLOCK);
if(fcntl(*sockfd, F_SETFL, socketFlags) <0){
qDebug()<<"Impossible to update sockets descriptor flags "<<strerror(errno);
return false;
}
if (setsockopt (*sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout)) < 0) {
qDebug()<< "ERR - setsockopt failed";
return false;
}
if (setsockopt (*sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
sizeof(timeout)) < 0) {
qDebug()<< "ERR - setsockopt failed";
return false;
}
if ((res = setsockopt (*sockfd, SOL_SOCKET, SO_SNDBUF, &buffersize,
sizeof(buffersize))) == -1) {
qDebug()<< "ERR - setsockopt failed (SO_SNDBUF) = " << res;
return false;
}
//Socket Ready
return true;
}
:이 부분에 대한
코드는 다음과 같습니다.
bool mastControl::findPacket(int sockfd, st_messageMastToPc * messageReceived, bool * connected) {
int n = 0;
bool messageFound = false;
char * buffer = (char *) messageReceived;
unsigned int pos = 0;
while (((n = read(sockfd, &(buffer[pos]), 1)) > 0) and not messageFound) {
//qDebug() << "read output " << n;
if (n == 1) {
pos++;
if ((pos == 1) && (buffer[0] == 2)) {
// Some stuff...
} else if ((pos == 2) && (buffer[1] == 2)) {
// Some stuff...
} else if (pos >= uiMessageMastToPcSize) {
messageFound = true;
//Complete message received
} else if (pos < 2) {
// Reseting pos
pos = 0;
}
}
}
if (n < 0){
qDebug()<< "Disconnected. Reason #" << errno << ": " << strerror(errno);
*connected = false;
}
return messageFound;
}
읽기 기능이 errno를로 EAGAIN을주고있다 "자원 일시적으로 사용할 수 없습니다"를 의미 : 나는 새로운 패킷을 읽을 접수가 있는지 확인하는 함수를 호출하고있어 어디 그러나 나는 루프가 있습니다. 그렇다면 내가 연결이 끊어져 있다고 가정하고, 불리언 연결이 이제는 거짓인데, 루프에서 다시 소켓을 생성하려고 다시 시도 할 것입니다.
그래서 처음에는 왜이 오류가 발생하는지 알지 못합니다.
둘째로, 나는 완전히 연결이 끊어 졌는지 알지 못합니다. 아니면이 오류가 발생한 후에 새 소켓을 만들 때 연결을 끊는 사람이 나입니다.
어떤 도움이 필요합니까?
좋아, 그게 내가 기대했던거야. 하지만 내가 말했듯이, 나는 select 후에 소켓을 다시 BLOCKING으로 설정했다. 그 연습이 틀렸어? 매번 전화를 걸기 전에 선택 전화를해야합니까? 뭔가 다른 것을 읽을 때까지 실행을 차단하는 다른 방법은 없습니까? –
어떻게 차단 모드로 설정 했습니까? 당신이'read'를 호출하기 전에 그것이 일어 났을 것이 확실합니까? 'SO_RCVTIMEO' 세트가 있습니까? –
소켓을 작성하고 BLOCKING으로 다시 구성하는 코드를 포함하여 편집했습니다. 그것은 확실히 읽기 전에 발생합니다. 그리고 네, 함수의 끝에서 볼 수 있듯이, 저는 SO_RCVTIMEO를 설정하고 있습니다. (나는 그런 식으로 상속 받았지만 작동하지 않는다고 생각합니다.) 틀렸어? –