Сокеты Java: мой входной поток сервера не будет считываться из выходного потока клиента? - PullRequest
3 голосов
/ 30 января 2012

РЕДАКТИРОВАТЬ: Ik это долго, но кто-нибудь знает, как программировать сокеты ??

Моя проблема немного смущает меня. У меня есть сервер, работающий на одном компьютере и на другом, к которому подключен клиент. Когда я набираю сообщение от клиента в консоль и отправляю его, сервер, кажется, не получает его. Кто-нибудь знает почему, потому что я тестировал с печатью на консоли в течение последних 3 часов и не могу понять это. Я относительно новичок в сокетах, так что не будь слишком резким, если я просто идиот.

Вот мой код для клиентской стороны:

import java.net.*;
import java.util.Scanner;
import java.io.*;

public class SocketClient {

public static void main(String [] args) {
    String host = "************";
    int port = 25565;

    StringBuffer instr = new StringBuffer();
    String TimeStamp;
    System.out.println("SocketClient initialized");

    try {
        InetAddress address = InetAddress.getByName(host);
        Socket connection = new Socket(address, port);

        BufferedOutputStream bos = new     BufferedOutputStream(connection.getOutputStream());
        OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");

        Scanner scan = new Scanner(System.in);
        String message = scan.nextLine();

        TimeStamp = new java.util.Date().toString();
        String process = "Server called on " + host + ":" + port + " at " + TimeStamp + ": " + message + (char) 13;

        osw.write(process);
        osw.flush();

        BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());

        InputStreamReader isr = new InputStreamReader(bis, "US-ASCII");

        int c;
        while ( (c = isr.read()) != 13)
            instr.append( (char) c);

        connection.close();
        System.out.println(instr);

    } catch (UnknownHostException e) {
        System.err.println("UnknownHostException: " + e);
    } catch (IOException e) {
        System.err.println("IOExcepion: " + e);
    }
}
}

Вот код для подключения клиента к серверу:

import java.io.IOException;
import java.net.*;

public class MultipleSocketServer {

public static Socket connection;
public static String name = "Tyler's Server";
public static int limit = 2;
public static Thread[] clients = new Thread[limit];
public static int current = 0;
public static int port = 25565;
public static String[] connected = {"", ""};
public static ServerSocket socket;

public static void main(String[] args) {
    System.out.println("Server starting...");
    try {
        ServerSocket socket = new ServerSocket(port);
        while(true) {
            Socket connection = socket.accept();
            String ip = connection.getRemoteSocketAddress().toString().substring(1, 13);
            loop:
            for(int i = 0; i < connected.length; i++) {
                if(connected[0].equals(ip) || connected[1].equals(ip)) {
                    break loop;
                }else if(!connected[i].equals(ip)) {
                    connected[i] = ip;
                    System.out.println(ip);
                    MultiServer_Client client = new     MultiServer_Client(connection, i);
                    Thread run = new Thread(client);
                    run.start();
                    break loop;
                }
            }
        }
    } catch (IOException e1) {
        System.out.println("Could not bind server on: " + port);
        System.exit(-1);
    }
}
}

А вот мой код для обработки каждого клиента как подключенного:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class MultiServer_Client implements Runnable {

public String time;
public Socket client;
public StringBuffer process = new StringBuffer();

public BufferedInputStream inputStream;
public InputStreamReader reader;

public BufferedOutputStream outputStream;
public OutputStreamWriter writer;

public boolean connected = true;

public int ID;

public MultiServer_Client(Socket connection, int i) {
    client = connection;
    ID = i;
    try {
        inputStream = new BufferedInputStream(client.getInputStream());
        reader = new InputStreamReader(inputStream);

        outputStream = new BufferedOutputStream(client.getOutputStream());
        writer = new OutputStreamWriter(outputStream, "US-ASCII");
    } catch (IOException e) {
        System.out.println("IOException: " + e);
    }
    System.out.println("Client connected...");
    write("Connected to " + MultipleSocketServer.name);
}

public void run() {
    while(connected) {
        write("hi");
    }
    System.out.println("Disconnecting client...");
}

public void write(String authen) {
    try {
        time = new java.util.Date().toString();
        String message = time + ": " + authen + (char) 13;
        writer.write(message);
        writer.flush();
    } catch (IOException e) {
        connected = false;
        MultipleSocketServer.connected[ID] = "";
    }
}

public void read() {
    //read from client
    int character;
    process = new StringBuffer();
    try {
        while ((character = reader.read()) != 13) {
            process.append((char) character);
        }
        System.out.println(process);
        process.delete(0, process.length());
    } catch (IOException e) {
        connected = false;
        MultipleSocketServer.connected[ID] = "";
    }
}
}

Извини, если я не могу сильно помочь. Как я уже сказал, я новичок в сокетах, и, похоже, ни у кого больше нет проблем с этим ... Спасибо:)

1 Ответ

6 голосов
/ 30 января 2012

Проблема с вашим кодом не в "сокетах", а в вашем протоколе связи.Вы фактически закрываете сокет до того, как у сервера появится возможность написать «привет».

Чтобы отладить это, вы хотите уменьшить сложность вашей программы.Есть ряд вещей, которые не имеют никакого смысла или значения в вашей программе.

Итак, немного истории о сокетах.Есть два типа розеток.«ServerSocket» и «Socket» ServerSocket вроде как секретарь.Его единственная задача - слушать звонки и затем передавать их.Это то, что делает «принять».Перед подключением любого клиента accept () будет блокироваться, пока не получит соединение.Как только клиент соединяется, accept возвращает Socket, представляющий соединение.

Обычный Socket - это место, где выполняется вся работа.Вы можете думать об этом как о телефонной связи.Вы можете общаться с кем-то удаленно с OutputStream и слушать, используя InputStream.Сложность заключается в том, что вам нужно создать какое-то соединение (называемое протоколом) для взаимодействия ваших двух сокетов.

Вам необходимо выяснить, как вы хотите разделить свои команды.Вы можете передать число фиксированной длины, а затем данные, если вы хотите использовать протокол с разделителями длины или вы можете использовать специальный символ для конца сообщения (что у вас есть в настоящее время).Для быстрых и грязных я часто использую последний с символом новой строки.Самый простой - просто использовать PrintWriter для записи и сканер для чтения.

Следующим шагом является выяснение схемы связи для клиента и сервера.Думайте, если это как передача мяча назад и вперед.Если клиент что-то говорит, другая сторона должна слушать (и наоборот).

Как только протокол и логика выяснены, вы можете затем переместить логику для «обработки» стороны сервера в отдельные потоки (называется рабочим шаблоном), так что сервер может обрабатывать более одного клиента одновременно.Если вы хотите пойти еще дальше, вы можете реализовать реактор с пулом потоков, чтобы на сервере не заканчивались потоки, но это, вероятно, для другого дня / вопроса.

Я бы порекомендовал следоватьУчебник Java по сокетам: http://docs.oracle.com/javase/tutorial/networking/sockets/index.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...