|  | @@ -31,6 +31,44 @@ def _handle_unary_unary(unused_request, unused_servicer_context):
 | 
	
		
			
				|  |  |      return _RESPONSE
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +def _get_reuse_socket_option():
 | 
	
		
			
				|  |  | +    try:
 | 
	
		
			
				|  |  | +        return socket.SO_REUSEPORT
 | 
	
		
			
				|  |  | +    except AttributeError:
 | 
	
		
			
				|  |  | +        # SO_REUSEPORT is unavailable on Windows, but SO_REUSEADDR
 | 
	
		
			
				|  |  | +        # allows forcibly re-binding to a port
 | 
	
		
			
				|  |  | +        return socket.SO_REUSEADDR
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def _pick_and_bind_port(sock_opt):
 | 
	
		
			
				|  |  | +    # Reserve a port, when we restart the server we want
 | 
	
		
			
				|  |  | +    # to hold onto the port
 | 
	
		
			
				|  |  | +    port = 0
 | 
	
		
			
				|  |  | +    for address_family in (socket.AF_INET6, socket.AF_INET):
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            s = socket.socket(address_family, socket.SOCK_STREAM)
 | 
	
		
			
				|  |  | +        except socket.error:
 | 
	
		
			
				|  |  | +            continue  # this address family is unavailable
 | 
	
		
			
				|  |  | +        s.setsockopt(socket.SOL_SOCKET, sock_opt, 1)
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            s.bind(('localhost', port))
 | 
	
		
			
				|  |  | +            # for socket.SOCK_STREAM sockets, it is necessary to call
 | 
	
		
			
				|  |  | +            # listen to get the desired behavior.
 | 
	
		
			
				|  |  | +            s.listen(1)
 | 
	
		
			
				|  |  | +            port = s.getsockname()[1]
 | 
	
		
			
				|  |  | +        except socket.error:
 | 
	
		
			
				|  |  | +            # port was not available on the current address family
 | 
	
		
			
				|  |  | +            # try again
 | 
	
		
			
				|  |  | +            port = 0
 | 
	
		
			
				|  |  | +            break
 | 
	
		
			
				|  |  | +        finally:
 | 
	
		
			
				|  |  | +            s.close()
 | 
	
		
			
				|  |  | +    if s:
 | 
	
		
			
				|  |  | +        return port if port != 0 else _pick_and_bind_port(sock_opt)
 | 
	
		
			
				|  |  | +    else:
 | 
	
		
			
				|  |  | +        return None  # no address family was available
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class ReconnectTest(unittest.TestCase):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def test_reconnect(self):
 | 
	
	
		
			
				|  | @@ -39,18 +77,9 @@ class ReconnectTest(unittest.TestCase):
 | 
	
		
			
				|  |  |              'UnaryUnary':
 | 
	
		
			
				|  |  |              grpc.unary_unary_rpc_method_handler(_handle_unary_unary)
 | 
	
		
			
				|  |  |          })
 | 
	
		
			
				|  |  | -        # Reserve a port, when we restart the server we want
 | 
	
		
			
				|  |  | -        # to hold onto the port
 | 
	
		
			
				|  |  | -        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            opt = socket.SO_REUSEPORT
 | 
	
		
			
				|  |  | -        except AttributeError:
 | 
	
		
			
				|  |  | -            # SO_REUSEPORT is unavailable on Windows, but SO_REUSEADDR
 | 
	
		
			
				|  |  | -            # allows forcibly re-binding to a port
 | 
	
		
			
				|  |  | -            opt = socket.SO_REUSEADDR
 | 
	
		
			
				|  |  | -        s.setsockopt(socket.SOL_SOCKET, opt, 1)
 | 
	
		
			
				|  |  | -        s.bind(('localhost', 0))
 | 
	
		
			
				|  |  | -        port = s.getsockname()[1]
 | 
	
		
			
				|  |  | +        sock_opt = _get_reuse_socket_option()
 | 
	
		
			
				|  |  | +        port = _pick_and_bind_port(sock_opt)
 | 
	
		
			
				|  |  | +        self.assertIsNotNone(port)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          server = grpc.server(server_pool, (handler,))
 | 
	
		
			
				|  |  |          server.add_insecure_port('[::]:{}'.format(port))
 |