多线程和网络编程实践——LittleTom

来源:互联网 发布:php base64 中文乱码 编辑:程序博客网 时间:2024/06/16 08:02

这两天写了一个小应用,实现基本的聊天功能。该应用既是客户端也是服务器,不要求某一方先发起连接请求。但同一时间仅能两个ip互相传输数据。用上了最近学的多线程和网络编程相关知识。先贴上初稿,还有问题,以后有空再琢磨琢磨。

两个类:LittleTom.class, TalkThread.class

1. LittleTom.java

import java.io.*;import java.net.*;public class LittleTom {    private Wait waitThread = null;    private Connect connectThread = null;    private ServerSocket waitSocket;    private Socket socket;    private BufferedReader br = null;    private int waitPort = 10001;    private int connectPort = 10002;    private boolean isConnecting = false;        public LittleTom() {        br = new BufferedReader(new InputStreamReader(System.in));                waitThread = new Wait();        connectThread = new Connect();                waitThread.start();        connectThread.start();    }       class Wait extends Thread {       public void run(){           waitConnect();       }              synchronized private void waitConnect() {           try {               waitSocket = new ServerSocket(waitPort);               while(true) {                                             if(!isConnecting) {                       Socket memberSocket = waitSocket.accept();                       if(!isConnecting) {                           isConnecting = true;                           System.out.println(memberSocket.getInetAddress().getHostName() + " want to talk with you.");                           new TalkThread(LittleTom.this, memberSocket);                       } else {                           System.out.println("Wait::You can only speak with one preson at the same time.");                           continue;                       }                   } else {                       wait();                   }               }           } catch(Exception e) {               e.printStackTrace();           } finally {               try {                   if(waitSocket != null){                       waitSocket.close();                   }                                     if(socket != null) {                       socket.close();                   }                   br.close();               } catch(Exception e) {                   e.printStackTrace();               }           }       }   }      class Connect extends Thread {       public void run(){           tryToConnect();       }       synchronized private void tryToConnect() {           try{               while(true) {                   if(!isConnecting) {                       System.out.println("Please input the IP that you want to talk with: ");                       br = new BufferedReader(new InputStreamReader(System.in));                       String input = br.readLine();//                       String IP = "109.123.102.117";                       if(!isConnecting) {                           isConnecting = true;                           System.out.println("Try to connecting...");                           socket = new Socket(input, connectPort);                           new TalkThread(LittleTom.this, socket);                                                   } else {                           System.out.println("Connect::You can only speak with one preson at the same time.");                           continue;                       }                   } else {                       wait();                   }               }           } catch(Exception e) {               System.out.println("connect fail.");               e.printStackTrace();           } finally {               try {                   if(waitSocket != null){                       waitSocket.close();                   }                                     if(socket != null) {                       socket.close();                   }                   br.close();               } catch(Exception e) {                   e.printStackTrace();               }           }       }   }      public void resetConnection() {        isConnecting = false;        synchronized(waitThread) {            waitThread.notify();        }        synchronized(connectThread) {            connectThread.notify();        }    }       public BufferedReader getSystemBuffer() {        return br;    }    public static void main(String[] args) {            LittleTom lt = new LittleTom();    }    }

2. TalkThread.java

import java.io.*;import java.net.*;public class TalkThread {    private LittleTom littleTom;    private Socket memberSocket;    private String peer;    private InputStream is;    private OutputStream os;        private Thread receiveThrd = null;    private Thread sendThrd = null;           public TalkThread(LittleTom lt, Socket socket){        try {            this.littleTom = lt;            this.memberSocket = socket;            peer = memberSocket.getInetAddress().getHostName();            is = memberSocket.getInputStream();            os = memberSocket.getOutputStream();             receiveThrd = new Thread() {                public void run(){                    receive();                    sendThrd.stop();                    close();                    littleTom.resetConnection();                }            };            sendThrd = new Thread() {                public void run(){                    send();                    receiveThrd.stop();                    close();                    littleTom.resetConnection();                }            };                        receiveThrd.start();            sendThrd.start();        } catch(Exception e) {            e.printStackTrace();        }     }    private void receive() {        byte[] b = new byte[1024];        String receiveMsg = null;        try {            do {                int n = is.read(b);                if(n<=0) {                    continue;                }                receiveMsg = new String(b, 0, n);                 System.out.println(peer + " say >>>> " + receiveMsg);            } while(receiveMsg == null || !receiveMsg.equalsIgnoreCase("exit"));        } catch(Exception e) {            if(memberSocket.isClosed()){                System.out.println("receive::socket is closed.");            } else {                e.printStackTrace();            }        }    }        private void send() {//        byte[] b = new byte[1024];        String input = null;        try {            do {                input = littleTom.getSystemBuffer().readLine();                if(input == null) {                    continue;                }                System.out.println("I say >>>> " + input);                os.write(input.getBytes());            } while((input == null) || (!input.equalsIgnoreCase("exit")));        } catch(Exception e) {        if(memberSocket.isClosed()){                System.out.println("send::socket is closed.");            } else {                e.printStackTrace();            }        }     }        public void close() {        try {            is.close();            os.close();            memberSocket.close();        } catch(Exception e) {            e.printStackTrace();        }    }}


    程序运行起来还有问题:

        1. 被动接受连接的一方,第一次用户输入的数据不能发送出去。原因是数据被tryToConnect读到,并被认为是用户输入的IP地址,所以尝试去连接。连接失败,打印"Connect::You can only speak with one preson at the same time.", 再次进入循环的时候,由于isConnecting==true,直接进入等待。然后后面用户的输入就能发送出去了。但是怎么修复这个bug啊?

        2. 连接只能进行一次。一方exit,然后再尝试去连就连不上了。但是程序并没有退出。求高手解答。

 

 


 

原创粉丝点击