Java Socket编程实现在终端上的双工Chat

理应是对等通信,不过Java Socket通信总要区分Server和Client。但Socket有

public InputStream getInputStream() throws IOException

public OutputStream getOutputStream() throws IOException

因而,我们可以用两个线程分别做输入(听)和输出(说)两件事,这样我们就可以在一个终端上既能输入数据也能显示对方发送过来的数据了。这篇文章的代码已经非常简明,我在实现自己代码的过程中向这篇文章学习了很多,完全可以只读这篇文章。

设计

为Server端和Client端分别实现两个继承Thread类的类,分别执行听和说两个任务。当开启Server端和Client端时,就开始这两个线程。例如在Server端的ChatServer.java中,我写了

class ServerReadingThread extends Thread
class ServerWritingThread extends Thread
public class ChatServer

在ChatServer的main方法里开启这两个线程。需要注意的是,ChatServer需要给定port,ChatClient需要指定server的地址和相同的port。例如在同一局域网内,我在主机A(Server,IP地址是192.168.1.142)的终端运行:

java ChatServer 6066

开启服务器端的两个进程。然后在主机B(Client)的终端运行:

java ChatClient 192.168.1.142 6066

之后,就可以在这两个终端上你来我往聊天了。但是有一个问题,Server不能被多次连接,这不合理,合理的应该是这样:当Client主动断开之后,Server端程序不会退出,且在Client再次连接时,两台主机又能双工通信了。目前,当Server端退出之后,再连接Server,两个终端并不能即时通信了。

控制台读取字符串

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in());

接着用

bf.readLine();

不断读入控制台数据。

Socket文件流

使用DataInputStream和DataOutputStream类来处理,从DataInputStream对象读入时使用它的readUTF()方法,向DataOutputStream对象写字符串时使用它的writeUTF(str)方法。


贴代码

ChatServer.java

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

class ServerReadingThread extends Thread
{
    private DataInputStream in;
    public ServerReadingThread(DataInputStream in)
    {
        this.in = in;
    }
    public void run()
    {
        try
        {
            String str;
            do 
            {
                str = in.readUTF();
                if(str.equals("end"))
                    System.exit(0);
                System.out.println(str);
            }while(!str.equals("end"));
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

class ServerWritingThread extends Thread
{
    private DataOutputStream out;
    public ServerWritingThread(DataOutputStream out)
    {
        this.out = out;
    }
    public void run()
    {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String str;
            do
            {
                str = br.readLine();
                out.writeUTF(str);
                if(str.equals("end"))
                    System.exit(0); 
            }while(!str.equals("end"));
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

public class ChatServer
{
    public static void main(String [] args)
    {
        int port = Integer.parseInt(args[0]);
        try
        {
            ServerSocket serverSocket = new ServerSocket(port);
            Socket server = serverSocket.accept();

            DataInputStream in = new DataInputStream(server.getInputStream());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());

            Thread listen = new ServerReadingThread(in);
            Thread speak = new ServerWritingThread(out);

            System.out.println("Enter 'end' to exit.");

            listen.start();
            speak.start();
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

ChatClient.java

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

class ClientReadingThread extends Thread
{
    private DataInputStream in;
    public ClientReadingThread(DataInputStream in)
    {
        this.in = in;
    }
    public void run()
    {
        try
        {
            String str;
            do
            {
                str = in.readUTF();
                if (str.equals("end"))
                    System.exit(0);
                System.out.println(str);
            }while(!str.equals("end"));
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

class ClientWritingThread extends Thread
{
    private DataOutputStream out;
    public ClientWritingThread(DataOutputStream out)
    {
        this.out = out;
    }
    public void run()
    {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String str;
            do
            {
                str = br.readLine();
                out.writeUTF(str);
                if (str.equals("end"))
                    System.exit(0);
            }while(!str.equals("end"));
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

public class ChatClient
{
    public static void main(String [] args)
    {
        String serverName = args[0];
        int port = Integer.parseInt(args[1]);
        try
        {
            Socket client = new Socket(serverName, port);

            DataInputStream in = new DataInputStream(client.getInputStream());
            DataOutputStream out = new DataOutputStream(client.getOutputStream());

            Thread listen = new ClientReadingThread(in);
            Thread speak = new ClientWritingThread(out);

            System.out.println("Enter 'end' to exit!");

            listen.start();
            speak.start();
        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值