String message = URLEncoder.encode("my message", "UTF-8");
try {
// instantiate the URL object with the target URL of the resource to
// request
URL url = new URL("http://www.example.com/comment");
// instantiate the HttpURLConnection with the URL object - A new
// connection is opened every time by calling the openConnection
// method of the protocol handler for this URL.
// 1. This is the point where the connection is opened.
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
// set connection output to true
connection.setDoOutput(true);
// instead of a GET, we're going to send using method="POST"
connection.setRequestMethod("POST");
// instantiate OutputStreamWriter using the output stream, returned
// from getOutputStream, that writes to this connection.
// 2. This is the point where you'll know if the connection was
// successfully established. If an I/O error occurs while creating
// the output stream, you'll see an IOException.
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
// write data to the connection. This is data that you are sending
// to the server
// 3. No. Sending the data is conducted here. We established the
// connection with getOutputStream
writer.write("message=" + message);
// Closes this output stream and releases any system resources
// associated with this stream. At this point, we've sent all the
// data. Only the outputStream is closed at this point, not the
// actual connection
writer.close();
// if there is a response code AND that response code is 200 OK, do
// stuff in the first if block
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
// otherwise, if any other status code is returned, or no status
// code is returned, do stuff in the else block
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
As 3 primeiras respostas às suas perguntas são listadas como comentários embutidos, ao lado de cada método, no exemplo HTTP POST acima.
De getOutputStream :
Retorna um fluxo de saída que grava nesta conexão.
Basicamente, acho que você tem uma boa compreensão de como isso funciona, então deixe-me reiterar nos termos dos leigos. getOutputStream
basicamente abre um fluxo de conexão , com a intenção de gravar dados no servidor. No exemplo de código acima, "message" pode ser um comentário que estamos enviando para o servidor que representa um comentário deixado em uma postagem. Quando você vê getOutputStream
, está abrindo o fluxo de conexão para gravação, mas na verdade não grava dados até ligar writer.write("message=" + message);
.
De getInputStream () :
Retorna um fluxo de entrada que lê desta conexão aberta. Uma SocketTimeoutException pode ser lançada ao ler a partir do fluxo de entrada retornado se o tempo limite da leitura expirar antes que os dados estejam disponíveis para leitura.
getInputStream
faz o oposto. Assim getOutputStream
, ele também abre um fluxo de conexão , mas a intenção é ler dados do servidor, não gravar nele. Se a conexão ou a abertura do fluxo falhar, você verá a SocketTimeoutException
.
E o getInputStream? Como só consigo obter a resposta em getInputStream, isso significa que ainda não enviei nenhuma solicitação no getOutputStream, mas simplesmente estabeleci uma conexão?
Lembre-se de que enviar uma solicitação e enviar dados são duas operações diferentes. Quando você chama getOutputStream ou getInputStream url.openConnection()
, envia uma solicitação ao servidor para estabelecer uma conexão. Há um handshake que ocorre onde o servidor retorna uma confirmação de que a conexão foi estabelecida. É nesse momento que você está preparado para enviar ou receber dados. Portanto, você não precisa chamar getOutputStream para estabelecer uma conexão para abrir um fluxo, a menos que seu objetivo para fazer a solicitação seja enviar dados.
Nos termos dos leigos, fazer um getInputStream
pedido é o equivalente a fazer uma ligação para a casa de seu amigo e dizer: "Ei, tudo bem se eu vier e pedir emprestado esse par de vagens?" e seu amigo estabelece o aperto de mão dizendo: "Claro! Venha e pegue". Então, nesse ponto, a conexão é estabelecida, você caminha para a casa de seu amigo, bate na porta, solicita as garras e volta para sua casa.
Usar um exemplo semelhante getOutputStream
envolveria ligar para seu amigo e dizer "Ei, eu tenho o dinheiro que lhe devo, posso enviar para você"? Seu amigo, precisando de dinheiro e doente por dentro, que você o guardou por tanto tempo, diz "Claro, vamos lá, seu bastardo barato". Então você vai até a casa do seu amigo e "paga" o dinheiro para ele. Ele então te expulsa e você volta para sua casa.
Agora, continuando com o exemplo do leigo, vejamos algumas exceções. Se você ligou para o seu amigo e ele não estava em casa, pode ser um erro de 500. Se você ligou e recebeu uma mensagem de número desconectado porque seu amigo está cansado de você pedir dinheiro emprestado o tempo todo, é uma página 404 não encontrada. Se seu telefone estiver morto porque você não pagou a conta, isso pode ser uma IOException. (OBSERVAÇÃO: Esta seção pode não estar 100% correta. Pretende fornecer uma idéia geral do que está acontecendo nos termos dos leigos.)
Pergunta 5:
Sim, você está certo de que o openConnection simplesmente cria um novo objeto de conexão, mas não o estabelece. A conexão é estabelecida quando você chama getInputStream ou getOutputStream.
openConnection
cria um novo objeto de conexão. Desde os javadocs URL.openConnection :
Uma nova conexão é aberta sempre, chamando o método openConnection do manipulador de protocolo para este URL.
A conexão é estabelecida quando você chama openConnection, e o InputStream, OutputStream, ou ambos, são chamados quando você os instancia.
Pergunta 6 :
Para medir a sobrecarga, geralmente envolvo um código de temporização muito simples em todo o bloco de conexão, como:
long start = System.currentTimeMillis();
log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );
// run the above example code here
log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );
Tenho certeza de que existem métodos mais avançados para medir o tempo e a sobrecarga de solicitação, mas isso geralmente é suficiente para minhas necessidades.
Para obter informações sobre o fechamento de conexões, sobre as quais você não perguntou, consulte Em Java, quando uma conexão de URL é fechada? .
Returns an output stream that writes to this connection.
andReturns an input stream that reads from this open connection.
. O fluxo de saída e o fluxo de entrada são separados da conexão.Tim Bray apresentou um conciso passo a passo, afirmando que openConnection () não estabelece uma conexão real. Em vez disso, uma conexão HTTP real não é estabelecida até você chamar métodos como getInputStream () ou getOutputStream ().
http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection
fonte
Na porta nomeada no URL, se houver, caso contrário, 80 para HTTP e 443 para HTTPS. Eu acredito que isso está documentado.
Quando você chama getInputStream () ou getOutputStream () ou getResponseCode () sem obter uma exceção.
Não e nenhum.
Qualquer um deles primeiro se conecta, se necessário, e depois retorna o fluxo necessário.
Veja acima.
Sim.
Conectar: reserve o tempo que getInoutStream () ou getOutputStream () leva para retornar, o que você chamar primeiro. Leitura: tempo desde o início da primeira leitura até a obtenção do EOS.
fonte
Em que ponto o HTTPURLConnection tenta estabelecer uma conexão com o URL fornecido?
Vale a pena esclarecer, há a instância 'UrlConnection' e a conexão de soquete Tcp / Ip / SSL subjacente , 2 conceitos diferentes. A instância 'UrlConnection' ou 'HttpUrlConnection' é sinônimo de uma única solicitação de página HTTP e é criada quando você chama url.openConnection (). Mas se você fizer vários url.openConnection () da instância 'url', se tiver sorte, eles reutilizarão o mesmo soquete Tcp / Ip e outras coisas de handshake SSL ... o que é bom se você estiver fazendo muitas solicitações de página para o mesmo servidor, especialmente se você estiver usando SSL, onde a sobrecarga de estabelecer o soquete é muito alta.
Consulte: Implementação HttpURLConnection
fonte
Fiz o exercício para capturar a troca de pacotes de baixo nível e descobri que a conexão de rede só é acionada por operações como getInputStream, getOutputStream, getResponseCode, getResponseMessage etc.
Aqui está a troca de pacotes capturada quando tento escrever um pequeno programa para fazer upload de arquivos no Dropbox.
Abaixo está o meu programa de brinquedos e anotação
fonte