@@ -171,6 +171,7 @@ function buildNodesOnly(proxies: Proxy[]): { proxies: Proxy[] } {
171171const TCP_TIMEOUT = 5000 ;
172172const TCP_CONCURRENCY = 50 ;
173173const TCP_RETRIES = 3 ;
174+ const TCP_RETRY_DELAY = 3000 ;
174175
175176function tcpCheckOnce ( host : string , port : number ) : Promise < boolean > {
176177 return new Promise ( ( resolve ) => {
@@ -181,14 +182,21 @@ function tcpCheckOnce(host: string, port: number): Promise<boolean> {
181182 } ) ;
182183}
183184
184- async function tcpCheck ( host : string , port : number ) : Promise < boolean > {
185- try {
186- return await Promise . any (
187- Array . from ( { length : TCP_RETRIES } , ( ) => tcpCheckOnce ( host , port ) ) ,
188- ) ;
189- } catch {
190- return false ;
185+ async function tcpBatch ( endpoints : [ string , { host : string ; port : number } ] [ ] ) : Promise < Set < string > > {
186+ const aliveSet = new Set < string > ( ) ;
187+ let tested = 0 ;
188+ for ( let i = 0 ; i < endpoints . length ; i += TCP_CONCURRENCY ) {
189+ const batch = endpoints . slice ( i , i + TCP_CONCURRENCY ) ;
190+ const results = await Promise . all ( batch . map ( async ( [ key , ep ] ) => ( { key, ok : await tcpCheckOnce ( ep . host , ep . port ) } ) ) ) ;
191+ for ( const r of results ) {
192+ if ( r . ok ) aliveSet . add ( r . key ) ;
193+ }
194+ tested += batch . length ;
195+ const pct = Math . round ( ( tested / endpoints . length ) * 100 ) ;
196+ process . stdout . write ( `\r ${ tested } /${ endpoints . length } (${ pct } %) 存活: ${ aliveSet . size } ` ) ;
191197 }
198+ process . stdout . write ( '\n' ) ;
199+ return aliveSet ;
192200}
193201
194202async function tcpFilterAll ( proxies : Proxy [ ] ) : Promise < Set < string > > {
@@ -198,24 +206,25 @@ async function tcpFilterAll(proxies: Proxy[]): Promise<Set<string>> {
198206 if ( ! uniqueEndpoints . has ( key ) ) uniqueEndpoints . set ( key , { host : p . server , port : p . port } ) ;
199207 }
200208
201- const endpoints = [ ...uniqueEndpoints . entries ( ) ] ;
209+ const allEndpoints = [ ...uniqueEndpoints . entries ( ) ] ;
202210 const aliveSet = new Set < string > ( ) ;
203- let tested = 0 ;
211+ let remaining = allEndpoints ;
204212
205- console . log ( `\nTCP 连通性测试 (${ endpoints . length } 个唯一端点)...` ) ;
213+ console . log ( `\nTCP 连通性测试 (${ allEndpoints . length } 个唯一端点, ${ TCP_RETRIES } 轮 )...` ) ;
206214
207- for ( let i = 0 ; i < endpoints . length ; i += TCP_CONCURRENCY ) {
208- const batch = endpoints . slice ( i , i + TCP_CONCURRENCY ) ;
209- const results = await Promise . all ( batch . map ( async ( [ key , ep ] ) => ( { key , ok : await tcpCheck ( ep . host , ep . port ) } ) ) ) ;
210- for ( const r of results ) {
211- if ( r . ok ) aliveSet . add ( r . key ) ;
215+ for ( let round = 1 ; round <= TCP_RETRIES ; round ++ ) {
216+ if ( remaining . length === 0 ) break ;
217+ if ( round > 1 ) {
218+ console . log ( ` 等待 ${ TCP_RETRY_DELAY / 1000 } s 后重试...` ) ;
219+ await new Promise ( r => setTimeout ( r , TCP_RETRY_DELAY ) ) ;
212220 }
213- tested += batch . length ;
214- const pct = Math . round ( ( tested / endpoints . length ) * 100 ) ;
215- process . stdout . write ( `\r TCP: ${ tested } /${ endpoints . length } (${ pct } %) 存活: ${ aliveSet . size } ` ) ;
221+ console . log ( ` 第 ${ round } 轮 (${ remaining . length } 个端点):` ) ;
222+ const roundAlive = await tcpBatch ( remaining ) ;
223+ for ( const key of roundAlive ) aliveSet . add ( key ) ;
224+ remaining = remaining . filter ( ( [ key ] ) => ! roundAlive . has ( key ) ) ;
216225 }
217- process . stdout . write ( '\n' ) ;
218- console . log ( `TCP 连通率: ${ aliveSet . size } /${ endpoints . length } (${ Math . round ( ( aliveSet . size / endpoints . length ) * 100 ) } %)` ) ;
226+
227+ console . log ( `TCP 连通率: ${ aliveSet . size } /${ allEndpoints . length } (${ Math . round ( ( aliveSet . size / allEndpoints . length ) * 100 ) } %)` ) ;
219228 return aliveSet ;
220229}
221230
0 commit comments