larbin源码分析(一) 从gloabl文件分析每一个结构
一 本系列主要是分析larbin开源爬虫的源代码,主要思路是先从global文件中的各个重要的结构开始。
1 Connexion 此处为一个结构体
该结构体主要的作用是进行连接服务器的操作。其中析构函数基本不执行,因为此结构是循环利用的,在
程序中保持一定的数量。小扩展:FetchOpen 类主要用来建立连接,而FetchPipe类主要用来进行连接之后的数据交换。
结构体中成员变量
struct Connexion{
char state ; //表示socket的状态EMPTY , CONNECTING , WRITE . OPEN
int pos ; //请求被发送到的位置
FetchError err ; //查询如何终止的
int socket ; // number of the fds
int timeout ; //链接的超时值
LarbinString request ; //http 请求报头
file * parser ; //对下载的网页进行解析
char buffer[maxPageSize] ; //存储下载的网页数据
Connexion() ;
~Connexion() ;
//recycle
void recycle() ; //此处主要进行循环使用
} ;
2 具体成员函数的实现
Connexion::Connexion() //具体将socket的状态变为emptyC
{ //将文件解析句柄变为空
state = emptyC ;
parser = NULL ;
}
Connexion::~Connexion() //保证一旦调用,即报告错误
{
assert(false) ;
}
/*recycle a connexion*/
void Connexion::recycle() //循环使用该结构体
{
delete parser ; //删除解析对象
request.recycle() ; //对LarbinString 调用recycle函数。
}
3 utils包下的connexion.h 和 connexion.cc的具体代码实现
// Larbin
// Sebastien Ailleret
// 15-11-99 -> 14-12-99
#ifndef CONNEXION_H
#define CONNEXION_H
/**//* make write until everything is written
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrire (int fd, char *buf);
/**//* make write until everything is written
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrireBuff (int fd, char *buf, int count);
/**//** Write an int on a fds
* (uses ecrire)
*/
int ecrireInt (int fd, int i);
int ecrireInt2 (int fd, int i);
int ecrireInti (int fd, int i, char *f);
int ecrireIntl (int fd, long i, char *f);
/**//** Write an int on a fds
* (uses ecrire)
*/
int ecrireLong (int fd, long i);
/**//* Write a char on a fds
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrireChar (int fd, char c);
#endif // CONNEXION_H
在connexion.h中各个成员函数的作用主要是向套接字中写入数据。
写入操作中主要使用了 write 系统调用。
unistd.h中
ssize_t write(int fd , char * buf , int count)
若是发生写错误,则返回值为-1 ,但是若此时的错误状态为EINTR ,则表示是发生了中断操作,此时应该继续进行写操作。
若是当前执行的写操作出现了等待的事情,则不需要报错,应该继续写,直到等待的事情结束。
(1) 误区
write并不是立即执行写操作,而是将数据写入进内核缓冲区。
一般内核区比较稳定,不会出现问题。
(4)下面是connexion的实现代码
// Larbin
// Sebastien Ailleret
// 15-11-99 -> 03-05-01
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <ctype.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <iostream>
#include "options.h"
using namespace std ;
/**//*********************************/
/**//* various functions for writing */
/**//* make write until everything is written
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrire (int fd, char *buf) {
int pos = 0 ;
int len = strlen(buf);
while(pos < len)
{
int i = write(fd , buf + pos, len - pos) ;
if(i == -1)
{
if(errno != EINTR)
{
pos = len + 1 ;
}
}
else{
pos += i ;
}
}
return pos != len ;
}
/**//* make write until everything is written
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrireBuff (int fd, char *buf, int count) {
int pos = 0;
while(pos < count)
{
int i = write(fd , buf + pos , count - pos) ;
if(i == -1)
{
switch(errno)
{
case EINTR :
break ;
default:
pos = count + 1 ;
perror("buf error") ;
break;
}
}
else
pos += i ;
}
return pos != count;
}
/**//** Write an int on a fds
* (uses ecrire)
*/
int ecrireInt (int fd, int i) {
char buf[20];
sprintf(buf, "%d", i);
return ecrire(fd, buf);
}
int ecrireInt2 (int fd, int i) {
char buf[20];
sprintf(buf, "%d%c", i/10, i%10 + '0');
return ecrire(fd, buf);
}
int ecrireInti (int fd, int i, char *f) {
char buf[100];
sprintf(buf, f, i);
return ecrire(fd, buf);
}
int ecrireIntl (int fd, long i, char *f) {
char buf[100];
sprintf(buf, f, i);
return ecrire(fd, buf);
}
/**//** Write an int on a fds
* (uses ecrire)
*/
int ecrireLong (int fd, long i) {
char buf[30];
sprintf(buf, "%ld", i);
return ecrire(fd, buf);
}
/**//* Write a char on a fds
* return 0 on success, 1 otherwise
* Don't work on non-blocking fds
*/
int ecrireChar (int fd, char c) {
int pos = 0;
while (pos < 1) {
int i = write(fd, &c, 1);
if (i == -1) {
if (errno != EINTR) {
pos = 2;
}
} else {
pos += i;
}
}
return pos != 1;
}
(5)综上
Connexion主要处理的是连接相关的信息,其connexion中主要实现的是,向套接字中写入数据。
下一个系列,处理的是LarbinString 相关,该类主要是处理http报头的。