2013-12-08 3 views
0

나는 POP3 클라이언트를 yahoo에 쓰려고했지만 유효한 명령을 보낼 때마다 socket에서 읽을 수 없습니다. 웹을 통해 plaintext을 처리하는 애플리케이션을 만드는 것은 안전하지 않지만 이제는 POP3에 대해 자세히 배우려하고 있습니다.Linux에서 C를 사용하는 일반 텍스트 POP3 클라이언트 - 서버에 명령을 보낸 후 오류 읽기

QT을 사용하여 그래픽 인터페이스를 만들고 있는데, 지금은 관련이 없다고 생각합니다. 나는 더 얻을

int openConnection(char ip[], int port) 
{ 
//descriptor of socket 
int sd; 

struct sockaddr_in server; 


//fill in server structure 
server.sin_family = AF_INET; 
server.sin_addr.s_addr = inet_addr (ip); 
server.sin_port = htons (port); 

//create communication socket 
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     //if cannot create, return error 
     return -2; 
    } 

if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1) 
    { 
    return -1; 
    } 

return sd; 

//values to be returned 
//-2 - could not create socket 
//-1 - could not connect to server 
//socket descriptor in case of success 
} 

:

telnet pop.mail.yahoo.com 110 
+OK hello from popgate-0.8.0.504347 pop011.mail.ir2.yahoo.com 
user validuser 
+OK password required. 
pass validpassword 
+OK maildrop ready, 100 messages (134513 octets) (13531) 

이 내가 연결을 여는 핸들하는 방법입니다 : 모든

첫째, 나는 야후 터미널에서 간단한 명령을 실행하여 plaintext 통신을 지원하는지 확인했다 전화를 걸면 소켓을 만들고 연결하는 데 문제가 있습니다.

int sd = openConnection ("188.125.68.106", 110) 

(188.125.68.106 = pop.mail.yahoo.com의 ip)

select 또는 epoll을 사용하지 않고 환영 메시지를 읽을 수도 있습니다.

char message[80]; 
read (sd, message, 80); 

메시지 :

+OK hello from popgate-0.8.0.504347 pop011.mail.ir2.yahoo.com 

가 나는 또한 유효하지 않은 명령의 모든 종류를 보내고, 오류가

int sd = openConnection ("188.125.68.106", 110) 
write (sd,"this command is invalid",80); 
char messageFromS [80]; 
bzero (messageFromS, 80); 
read (sd,messageFromS,80); 

을 돌려 읽고 내가

-ERR invalid command  
의 라인 사이에 뭔가를 얻을 수 있습니다

하지만 언제든지 유효한 명령을 종료, 내 클라이언트가 방금 읽은 호출 한 후 정지됩니다 그리고 난 이후

write (sd,"user validuser",80); 
char messageFromS [80]; 
bzero (messageFromS, 80); 
read (sd,messageFromS,80); 

를 강제 종료해야한다, 나는 그것이 좋은 연습 알고 있기 때문에 select()을 사용하기로 결정하고, 어쩌면 좋은 결과

에게 줄 수
//function returns true (1) if we can read from the socket 
bool isClosed(int sock) 
{ 
fd_set rfd; 
FD_ZERO(&rfd); 
FD_SET(sock, &rfd); 
timeval tv; 

//timeout value is set to 5 seconds 
tv.tv_sec = 5; 

select(sock+1, &rfd, 0, 0, &tv); 
if (!FD_ISSET(sock, &rfd)) 
    return false; 
int n = 0; 
ioctl(sock, FIONREAD, &n); 
return n == 0; 
} 

그러나 내가

isClosed(sd) 

를 호출 할 때마다 항상 True를 반환 것으로 보인다.

이것은 다른 옵션을 생각할 수없는 지점입니다. Telnet에 내 미니어처 클라이언트가 가지고 있지 않은 것이 있습니까?

편집 : 답변 해 주셔서 감사합니다. pop3 (http://tools.ietf.org/html/rfc1081)에 대한 RFC를 다시 읽은 후 종료 문자 (분명히 NULL이 아니 었음)가 발견 될 때까지 바이트 단위로받은 모든 메시지를 읽음으로써 놀았습니다. 내 명령을 제대로 끝내. 내가 보낸 모든 명령의 끝에 '\ r'과 '\ n'을 추가해야합니다. 또한 select() 명령을 검사하여 -1을 반환하고 tv.tv_usec = 0으로 설정하여 거의 해결했습니다.

+1

밀접하게, 읽기()/쓰기 (의 인간이 페이지를 읽기) 그들이에 들었다 적어도 소켓이 두 기능이 반드시 많은 바이트를 전송/수신하지 않는 것을 알고 있지만, 조금. 따라서 모든 데이터가 수신/전송 될 때까지 계산 된 이러한 호출을 반복하는 것은 좋은 생각입니다. 꼭 필요한 것은 아닙니다. 수신 할 데이터의 양을 모를 경우 바이트 단위로 읽으십시오. – alk

+1

'select'의 반환 값을 확인해야합니다. 나는 그것이 -1이고'errno'가'EINVAL'으로 설정되어있을 것입니다. 내가 생각하는 이유는'tv' 구조체를 적절하게 초기화하지 않기 때문입니다. 'tv_usec' 멤버는 무작위 값이고 아마 불법입니다. –

+2

아, 물론 실패 할 수있는 모든 기능에서 오류를 확인해야합니다. 함수가 실제로 실패하지 않는 한'errno'를 체크하지 마십시오. –

답변

0

답장을 보내 주셔서 감사합니다. pop3 (http://tools.ietf.org/html/rfc1081)에 대한 RFC를 다시 읽은 후 종료 문자 (분명히 NULL이 아니 었음)가 발견 될 때까지 바이트 단위로받은 모든 메시지를 읽음으로써 놀았습니다. 내 명령을 제대로 끝내. 내가 보낸 모든 명령의 끝에 '\ r'과 '\ n'을 추가해야합니다. 또한 select() 명령을 검사하여 -1을 반환하고 tv.tv_usec = 0으로 설정하여 거의 해결했습니다.

- Shoshinsha purogurama