Java网络编程从客户端读取数据

时间:2016-06-24 21:02:36

标签: java networking network-programming inputstream

我是网络编程的新手。我想制作一个简单的服务器/客户端程序,以了解套接字的基础知识。但不幸的是,我无法理解一个概念。我可以在客户端发送消息之前调用readUTF()方法吗?因为当我第二次调用这个方法时,我的程序崩溃了。

错误:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at Messaging.ServerSideConnection.receiveData(ServerSideConnection.java:59)
at Messaging.Server.printInputs(Server.java:88)
at Messaging.Server$2.run(Server.java:35)
at java.lang.Thread.run(Unknown Source)

服务器:

package Messaging;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {

private static final String configId = "SERVER_CONFİG_ID_";

private static final int port = 6066;
private volatile ArrayList<ServerSideConnection> connections;

public static void main(String[] args){
    new Server();
}

public Server(){
    connections = new ArrayList<>();

    Thread acceptConnections = new Thread(new Runnable(){
        public void run() {
            try {
                acceptConnections(port);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });

    Thread printInputs = new Thread(new Runnable(){
        public void run() {
            while(true){
                printInputs();
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

    acceptConnections.start();
    printInputs.start();

    try {
        acceptConnections.join();
        printInputs.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void acceptConnections(int port) throws IOException{
    ServerSocket serverSocket = new ServerSocket(port);
    while(true){
        System.out.println("SERVER : Listening..");
        ServerSideConnection connection = new ServerSideConnection(serverSocket.accept());
        connection.sendData(configId + Integer.toString(connection.getId()));
        connections.add(connection);
        System.out.println("SERVER : Connected to " + connection.getSocket().getInetAddress());
    }
}

public void controlConnectionLife(){
    int instantSize = connections.size();
    for(int i=0;i<instantSize;i++){
        if(!connections.get(i).isConnected()){
            connections.get(i).killConnection();
            connections.remove(i);
            i--;
        }
    }
}

public void printInputs(){
    for (ServerSideConnection connection : connections){
        System.out.println(connection.isConnected());
        try {
            System.out.println(connection.receiveData());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ServerSideConnection {

private static int count;
private int id;

private Socket socket;
private DataInputStream input;
private DataOutputStream output;

public ServerSideConnection(Socket socket){
    this.socket = socket;

    initOutputStream();
    initInputStream();

    count++;
    id = count;
}

private void initInputStream(){
    try {
        InputStream in = socket.getInputStream();
        input = new DataInputStream(in);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void initOutputStream(){ 
    try {
        output = new DataOutputStream(socket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void killConnection(){
    try {
        output.close();
        input.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public String receiveData() throws IOException{
    return input.readUTF();
}

public void sendData(String msg) throws IOException{
    output.writeUTF(msg);
    output.flush();
}

public boolean isConnected(){
    return socket.isConnected();
}

public int getId(){
    return id;
}

public Socket getSocket(){
    return socket;
}

public DataInputStream getInput() {
    return input;
}

public DataOutputStream getOutput() {
    return output;
}

}

客户端:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientSideConnection {

private static final String configId = "SERVER_CONFİG_ID_";

private static final int port = 6066;
private static final String host = "localhost";

private int id;

private Socket socket;
private DataInputStream input;
private DataOutputStream output;

public static void main(String[] args){
    try {
        new ClientSideConnection(port,host);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public ClientSideConnection(int port, String host) throws UnknownHostException, IOException{
    boolean connected = false;
    while(!connected){
        try{
            socket = new Socket(host,port);
            connected = true;
            System.out.println("CLIENT : Connected to " + socket.getInetAddress());
        }
        catch(ConnectException e){
            connected = false;
        }
    }
    initOutputStream();
    initInputStream();


    String receivedId = receiveData();
    if(receivedId.substring(0, 17).equals(configId))
        id = Integer.parseInt(receivedId.substring(17,receivedId.length()));
    sendTestData();
}

private void initInputStream(){
    try {
        input = new DataInputStream(socket.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void initOutputStream(){
    try {
        output = new DataOutputStream(socket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void killConnection(){
    try {
        output.close();
        input.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public String receiveData() throws IOException{
    return input.readUTF();
}

public void sendData(String msg) throws IOException{
    output.writeUTF(msg);
    output.flush();
}

public int getId() {
    return id;
}

public void sendTestData(){
    Scanner scan = new Scanner(System.in);
    System.out.print("enter test msg: ");
    String msg = scan.nextLine();
    try {
        sendData(msg);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("msg sended!");
}
}

1 个答案:

答案 0 :(得分:2)

正如异常消息所述,对readUTF的第二次调用失败,因为客户端正在关闭连接。运行客户端的代码目前遵循以下序列:

  1. 建立连接
  2. 设置输入和输出流
  3. 从服务器读取数据
  4. 将数据发送到服务器
  5. 将数据发送到服务器后,没有代码,也没有循环重复发送/接收过程,因此客户端关闭其连接结束并退出。您需要在序列中添加第5步:

    1. 建立连接
    2. 设置输入和输出流
    3. 从服务器读取数据
    4. 将数据发送到服务器
    5. 跳至3直至满足停止条件
    6. 此序列的一种方法可能是:

      public class Client {
          public static void main(String[] args) {
      
              Client client = new Client();
              boolean sucessful;
      
              do {
                  String data = client.receiveData();
                  successful = client.sendData(data);
              } while(successful);
      
              client.close();
          }
      
          public Client() {
              //setup connection and in/output streams
          }
      
          public String receiveData() {
              //read from input
          }
      
          public boolean sendData(String data) {
              //send data
          }
      
          public void close() {
          }
      }