나는 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으로 설정하여 거의 해결했습니다.
밀접하게, 읽기()/쓰기 (의 인간이 페이지를 읽기) 그들이에 들었다 적어도 소켓이 두 기능이 반드시 많은 바이트를 전송/수신하지 않는 것을 알고 있지만, 조금. 따라서 모든 데이터가 수신/전송 될 때까지 계산 된 이러한 호출을 반복하는 것은 좋은 생각입니다. 꼭 필요한 것은 아닙니다. 수신 할 데이터의 양을 모를 경우 바이트 단위로 읽으십시오. – alk
'select'의 반환 값을 확인해야합니다. 나는 그것이 -1이고'errno'가'EINVAL'으로 설정되어있을 것입니다. 내가 생각하는 이유는'tv' 구조체를 적절하게 초기화하지 않기 때문입니다. 'tv_usec' 멤버는 무작위 값이고 아마 불법입니다. –
아, 물론 실패 할 수있는 모든 기능에서 오류를 확인해야합니다. 함수가 실제로 실패하지 않는 한'errno'를 체크하지 마십시오. –