DialTCP 创建 TCP 连接,内含限速检查、代理、计数
(ctx context.Context, network, address string, timeout time.Duration)
| 35 | |
| 36 | // DialTCP 创建 TCP 连接,内含限速检查、代理、计数 |
| 37 | func (s *ScanSession) DialTCP(ctx context.Context, network, address string, timeout time.Duration) (net.Conn, error) { |
| 38 | // 检查发包限制 |
| 39 | if ok, err := CanSendPacketWith(s.Config, s.State); !ok { |
| 40 | LogError(fmt.Sprintf("TCP连接 %s 受限: %s", address, err.Error())) |
| 41 | return nil, fmt.Errorf("发包受限: %s", err.Error()) |
| 42 | } |
| 43 | |
| 44 | // 获取 dialer |
| 45 | dialer, err := s.getDialer() |
| 46 | if err != nil { |
| 47 | LogError(fmt.Sprintf("获取代理拨号器失败: %v", err)) |
| 48 | s.State.IncrementTCPFailedPacketCount() |
| 49 | return nil, err |
| 50 | } |
| 51 | |
| 52 | conn, err := dialer.DialContext(ctx, network, address) |
| 53 | if err != nil { |
| 54 | s.State.IncrementTCPFailedPacketCount() |
| 55 | LogDebug(fmt.Sprintf("连接 %s 失败: %v", address, err)) |
| 56 | return nil, err |
| 57 | } |
| 58 | |
| 59 | // SO_LINGER=0: 连接关闭时立即发送 RST,避免 TIME_WAIT 堆积 |
| 60 | if tc, ok := conn.(*net.TCPConn); ok { |
| 61 | _ = tc.SetLinger(0) |
| 62 | } |
| 63 | |
| 64 | s.State.IncrementTCPSuccessPacketCount() |
| 65 | return conn, nil |
| 66 | } |
| 67 | |
| 68 | func (s *ScanSession) getDialer() (proxy.Dialer, error) { |
| 69 | s.dialerOnce.Do(func() { |
no test coverage detected