Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Проблемы соединения с некоторыми web-серверами


Автор: JlOKu 28.7.2009, 05:07
Всем доброго времени суток, вот уже два дня никак немогу решить проблему с подключением к некоторым web-серверам например youtube.com, sibir.megafon.ru, microsoft.ru пока это список не расширялся.

Я написал программу тоннелирования, что-то вроде прокси. Получив от браузера заголовок я из него вычитываю Host: и подключаюсь с помощью сокета и отправляю полученный заголовок, и жду ответа, все сайты нормально выдают ответы, кроме выше перечисленных, на них Socket реагирует не иначе как java.net.SocketException: Connection reset to peer SocketInputStreamRead(Native methode), я бы подумал что сайты не работают, но при подключнии к ним через другой прокси все работает отлаженно. 
Код

package ru.nsk.struchkov.ServerSide;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.InetAddress;


/*
 * @Author Struchkov L.F 
 * @Classname - ReadWriteThread : connect to HTTP server and data response to remote client
 * @Version -  0.0.1
 * @Date 12.06.09
 */ 

public class ReadWriteThread extends Thread{

    private Socket clientSocket = null;
    private Socket httpServerSocket = null;
    private ReadWriteThread coupleThread = null;         

    private byte[] buffer = new byte[BUFFER_SIZE];
            
    public static int qThread = 0;

    public ReadWriteThread(Socket clientSocket)throws IOException{
    this.clientSocket = clientSocket;            
    }

// configuration                    

    public Socket getClientSocket() {
    return clientSocket;
    }            

// configuration
    
    public Socket getHttpServerSocket() {
    return httpServerSocket;
    }                
    
// implementation    
                                                
    public void run() {
        qThread++;
    System.out.println("Thread count _____ " + qThread);
    try {

        DataInputStream inputClientStream = new DataInputStream(clientSocket.getInputStream());
        DataOutputStream outputClientStream = new DataOutputStream(clientSocket.getOutputStream());    
        byte[] buffer = new byte[BUFFER_SIZE];
        
        int count = 0;
        String header = "";

        // Read HTTP header from remote client
        while((count = inputClientStream.read(buffer)) == BUFFER_SIZE) {
        header += new String(buffer);        
        }

        byte[] tmpBuffer = new byte[count];
        System.arraycopy(buffer,0, tmpBuffer,0,count);    
        header += new String(tmpBuffer);
        
        // Get host name from HTTP header
        HTTPRequestParser httpParser = new HTTPRequestParser(header);

        // Convert from host name to IP address
        InetAddress inetAddress = InetAddress.getByName(httpParser.getHost());

        // Open socket on deafult HTTP port - 80
        httpServerSocket = new Socket(inetAddress.getHostAddress(), HTTP_PORT);
             
        DataInputStream inServerStream = new DataInputStream(httpServerSocket.getInputStream());        
        DataOutputStream outServerStream = new DataOutputStream(httpServerSocket.getOutputStream());
    
        // Send HTTP header to WEB-server
        outServerStream.writeBytes(header);
        outServerStream.flush();
        int readByteLenght = 0;    

         while(true){
           // Read response from WEB-server
           if ((readByteLenght = inServerStream.read(buffer)) == -1){  
              break; 
           }
           // Send response to remote client
           outputClientStream.write(buffer,0,readByteLenght);
        }

        outputClientStream.flush();
        System.out.println("One more client service--------------------");
        
        clientSocket.close();
        httpServerSocket.close();

    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        qThread--;    
    }
    
    System.out.println("Thread Close___________________>>>>>");
    }

    public static int BUFFER_SIZE = 64*1000;
    public static int HTTP_PORT = 80;
}


Собственно данный класс занимается соединением к WEB-серверу (получает от удаленного клиента заголовок, вынимает из него host name, соединяется с web-сервером, получает ответ, передает ответ удаленному клиенту)
За ранее спасибо

Автор: COVD 28.7.2009, 15:21
Цитата

вырезаю Host:

ну вот и получили проблемы. Это обязательное поле в заголовке запроса  

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 :


A client MUST include a Host header field in all HTTP/1.1 request messages . If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value. An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy. All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field. 

Автор: JlOKu 28.7.2009, 17:05
Цитата(COVD @ 28.7.2009,  15:21)
Цитата

вырезаю Host:

ну вот и получили проблемы. Это обязательное поле в заголовке запроса  

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 :


A client MUST include a Host header field in all HTTP/1.1 request messages . If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value. An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy. All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field.

Извините COVD за то, что ввел вас в заблуждение, я вычитываю host, а не вырезаю.

Автор: COVD 28.7.2009, 20:26
Как странно вы читаете заголовок.  Заголовок - это текст, оканчивающийся двумя пустыми строками \r\n\r\n, т.е. байты 13 10 13 10.  И данные из сокетного соединения могут приходить порциями теоретически по одному байту.
 
Код

      // Read HTTP header from remote client
        while((count = inputClientStream.read(buffer)) == BUFFER_SIZE) {
        header += new String(buffer);        
        }



Раз это обычный прокси, то возможно проще найти готовый с открытым кодом и добавить свою функциоальность. 

Автор: JlOKu 30.7.2009, 21:50
Спасибо большое COVD,  как только я начал определять конец заголовка как \r\n\r\n заработала, пришлось попариться немного конечно, готовый прокси не подошел бы потому, что данную прогу надо было запускать на хостинге где большие ограничения на ресурсы (количество соз-х потоков не должно превышать 36, память не больше n)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)