Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux中使用C的明文POP3客户端-向服务器发送命令后读取错误_C_Linux_Sockets_Client_Pop3 - Fatal编程技术网

在Linux中使用C的明文POP3客户端-向服务器发送命令后读取错误

在Linux中使用C的明文POP3客户端-向服务器发送命令后读取错误,c,linux,sockets,client,pop3,C,Linux,Sockets,Client,Pop3,我一直在尝试为yahoo编写一个POP3客户端,但是每当我发送一个有效的命令时,我都无法从socket读取。我知道在网上创建处理明文的应用程序是不安全的,但我现在只是想了解更多关于POP3的信息 我正在使用QT创建一个图形界面,但我认为这与现在无关 首先,我通过在终端中运行简单的命令来确保yahoo支持纯文本通信: telnet pop.mail.yahoo.com 110 +OK hello from popgate-0.8.0.504347 pop011.mail.ir2.yahoo.com

我一直在尝试为yahoo编写一个
POP3
客户端,但是每当我发送一个有效的命令时,我都无法从
socket
读取。我知道在网上创建处理
明文的应用程序是不安全的,但我现在只是想了解更多关于
POP3
的信息

我正在使用
QT
创建一个图形界面,但我认为这与现在无关

首先,我通过在终端中运行简单的命令来确保yahoo支持
纯文本
通信:

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)
以下是我处理打开连接的方式:

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
}
我在创建套接字和连接时没有问题

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    
但每当我发送一个有效的命令时,我的客户机在调用read后就会冻结,我必须强制退出

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)
它总是返回真的

在这一点上,我想不出任何其他选择。Telnet有我的微型客户端没有的东西吗

编辑:谢谢你的回答。 我一个字节一个字节地读取接收到的所有消息,直到它找到一个终止字符(显然它不是NULL),在仔细阅读了RFC for pop3()之后,我意识到我没有正确地结束命令。我应该在发送的所有命令的末尾附加'\r'和'\n'。
我还检查了select()命令,该命令返回-1,并将tv.tv_usec设置为0,这基本上解决了这个问题。

谢谢您的回答。 我一个字节一个字节地读取接收到的所有消息,直到它找到一个终止字符(显然它不是NULL),在仔细阅读了RFC for pop3()之后,我意识到我没有正确地结束命令。我应该在发送的所有命令的末尾附加'\r'和'\n'。 我还检查了select()命令,该命令返回-1,并将tv.tv_usec设置为0,这基本上解决了这个问题


–Shoshinsha purogurama

仔细阅读read()/write()的手册页,了解至少对于套接字,这两个函数接收/发送的字节数不一定像它们被告知的那么多,但很少。因此,在所有数据接收/发送之前循环此类呼叫计数是一个好主意,更不用说是必要的。如果您不知道要接收的数据量,请逐字节读取。您应该检查
选择中的返回值。我打赌它是
-1
,并且
errno
设置为
EINVAL
。我这样认为是因为没有正确初始化
tv
结构。
tv\u usec
成员将是一个随机值,并且可能是非法的。哦,当然,您应该检查所有可能失败的函数的错误。并且不要检查
errno
,除非函数确实失败。