Java Tcp Socket聊天系统模型

Tcp Socket是面向连接的,所以Server端的accept()方法,一直等着客户端的连接,如果连接成功,则两者进行通信,这种是同步的,因为accept()一直在那儿等着,时刻的等着,实际中的聊天系统是采用异步方式,当有请求的时候就调用accept()方法,没有请求的时候该做什么就做什么去,不需要在那儿等着,不浪费资源,一种异步的方式。这个例子只是为了学习线程而准备的。 
端口有TCP端口和UDP端口两种,端口号都是从0到65535,TCP端口在3层,UDP不是四层就是7层 TCP和UDP的协议也不相同,TCP比UDP安全,更多TCP和UDP区别上google,baidu。 

服务器端编码  
Java代码   收藏代码
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintStream;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.util.StringTokenizer;  
  8. import java.util.Vector;  
  9.   
  10. /** 
  11.  * 服务器端编码 
  12.  * @author 欧阳平 2009-3-17  
  13.  */  
  14. public class ChatServer {  
  15.     static int port = 5566;//端口号  
  16.     static Vector<Client> clients = new Vector<Client>(10);//存储连接客户信息  
  17.     static ServerSocket server = null//建立服务器socket  
  18.     static Socket socket = null//套接字连接  
  19.     /** 
  20.      * Constructs 
  21.      */  
  22.     public ChatServer() {  
  23.         try {  
  24.             System.out.println("Server start...");  
  25.             server  = new ServerSocket(port); //初始化服务器套接字  
  26.             while (true) {  
  27.                 socket = server.accept(); //等待连接  
  28.                 System.out.println(socket.getInetAddress()+"连接\n");//得到客户机地址  
  29.                 Client client = new Client(socket); //实例化一个客户线程(其中线程Client中有Socket,这里的的Socket只是起个过度作用)  
  30.                 //  
  31.                 clients.add(client);//增加客户线程到向量中  
  32.                 client.start();//启动线程  
  33.                 notifyChatRoom(); //监视聊天室连接变化  
  34.             }  
  35.         } catch (Exception ex) {  
  36.             ex.printStackTrace();//输出出错信息  
  37.         }  
  38.     }  
  39.       
  40.     public static void notifyChatRoom() { //监视客户端线程  
  41.         StringBuffer newUser = new StringBuffer("newUser");  
  42.         for (int i = 0; i < clients.size(); i++) {  
  43.             Client c = (Client)clients.elementAt(i);  
  44.             newUser.append(":"+c.name); //客户端姓名字符串  
  45.         }  
  46.         sendClients(newUser);//发送信息到客户端  
  47.     }  
  48.       
  49.     public static void sendClients(StringBuffer message) {  
  50.         for (int i= 0 ; i < clients.size(); i++) {  
  51.             Client client = (Client)clients.elementAt(i);//分别得到每个客户端的连接  
  52.             client.send(message);//发送信息  
  53.         }  
  54.     }  
  55.       
  56.     public void closeAll() { //关闭所有连接  
  57.         while (clients.size() > 0 ) { //遍历整个Vector  
  58.             Client client = (Client) clients.firstElement(); //得到一个客户端  
  59.             try {  
  60.                 client.socket.close();  
  61.             } catch(IOException ex) {  
  62.                 ex.printStackTrace(); // 输出错误信息  
  63.             }  
  64.             clients.removeElement(client); //移出客户端  
  65.         }  
  66.     }  
  67.       
  68.     public static void disconnect(Client c) {// 断开客户端  
  69.         try {  
  70.             System.err.println(c.ip+"断开连接\n");  
  71.         } catch (Exception ex) {  
  72.             ex.printStackTrace();  
  73.         }  
  74.         clients.removeElement(c);  
  75.         c.socket = null;  
  76.     }  
  77.       
  78.       
  79.     /** 
  80.      * main方法 
  81.      * @param args 
  82.      */  
  83.     public static void main(String[] args) {  
  84.         new ChatServer();  
  85.   
  86.     }  
  87.     class Client extends Thread {  
  88.         Socket socket;//连接端口  
  89.         String name ;//用户姓名  
  90.         String ip; //客户端ip地址  
  91.         BufferedReader reader;//输入流  
  92.         PrintStream ps;//输出流  
  93.         public Client(Socket s) {  
  94.             socket = s;  
  95.             try {  
  96.                 reader = new BufferedReader(new InputStreamReader(s.getInputStream()));//得到输入流  
  97.                 ps = new PrintStream(s.getOutputStream());//得到输出流  
  98.                 String info = reader.readLine();//读取接收到的信息  
  99.                 StringTokenizer stinfo = new StringTokenizer(info,":"); //分解字符串  
  100.                 String head = stinfo.nextToken(); //获取关键字  
  101.                 System.out.println(stinfo.toString());  
  102.                 System.out.println(head);  
  103.                 if (stinfo.hasMoreTokens()){  
  104.                     name = stinfo.nextToken() ;//获取用户名  
  105.                 }  
  106.                 if (stinfo.hasMoreTokens()) {  
  107.                     ip = stinfo.nextToken(); //获取IP地址  
  108.                 }  
  109.             } catch (IOException ex) {  
  110.                 ex.printStackTrace();  
  111.             }  
  112.             System.out.println(name);  
  113.             System.out.println(ip);  
  114.         }  
  115.           
  116.         public void send (StringBuffer msg) {  
  117.             ps.println(msg); //输出信息  
  118.             ps.flush();  
  119.         }  
  120.         public void run() {  
  121.             while (true) {  
  122.                 String line = null;  
  123.                 try {  
  124.                       
  125.                     line = reader.readLine();  
  126.                     System.out.println("line:"+line);  
  127.                       
  128.                 } catch (IOException ex) {  
  129.                     ex.printStackTrace(); //输出错误信息  
  130.                     ChatServer.disconnect(this);//断开连接  
  131.                     ChatServer.notifyChatRoom();//更新信息  
  132.                     return ;  
  133.                 }  
  134.                 if (line == null) { //客户离开  
  135.                     ChatServer.disconnect(this);  
  136.                     ChatServer.notifyChatRoom();  
  137.                     return ;  
  138.                 }  
  139.                 StringTokenizer st = new StringTokenizer(line,":");//分解字符串  
  140.                 String keyword = st.nextToken();  
  141.                 if (keyword.equals("MSG")) { //发送来的聊天信息  
  142.                     StringBuffer msg = new StringBuffer("MSG:");  
  143.                     msg.append(name); //在信息上增加用户名  
  144.                     msg.append(st.nextToken("\0\n"));  
  145.                     ChatServer.sendClients(msg);//发送聊天语句到各个客户端  
  146.                     System.out.println(msg);  
  147.                 } else if (keyword.equals("quit")) { //退出命令  
  148.                     ChatServer.disconnect(this); //断开连接  
  149.                     ChatServer.notifyChatRoom(); //刷新信息  
  150.                 }  
  151.             }  
  152.         }  
  153.     }  
  154.       
  155. }  



//客户端编码  
Java代码   收藏代码
  1. import java.awt.BorderLayout;  
  2. import java.awt.Button;  
  3. import java.awt.Color;  
  4. import java.awt.Label;  
  5. import java.awt.TextArea;  
  6. import java.awt.TextField;  
  7. import java.awt.event.ActionEvent;  
  8. import java.awt.event.ActionListener;  
  9. import java.io.BufferedReader;  
  10. import java.io.IOException;  
  11. import java.io.InputStreamReader;  
  12. import java.io.PrintStream;  
  13. import java.net.InetAddress;  
  14. import java.net.Socket;  
  15. import java.util.StringTokenizer;  
  16.   
  17. import javax.swing.JFrame;  
  18. import javax.swing.JOptionPane;  
  19. import javax.swing.JPanel;  
  20.   
  21. /** 
  22.  * 基于Socket网络聊天程序 客户端编码 
  23.  * @author 欧阳平 2009-3-17  
  24.  */  
  25. public class ChatClient extends JFrame  implements ActionListener,Runnable{  
  26.       
  27.     TextField tfName = new TextField(15);//姓名输入文本域  
  28.     Button btConnect = new Button("连接");//连接按钮  
  29.     Button btDisconnect = new Button("断开连接");//断开连接按钮  
  30.     TextArea tfChat = new TextArea(8,27);//显示聊天信息文本域  
  31.     Button btSend = new Button("发送");  
  32.     TextField tfMessage = new TextField(30);//聊天输入  
  33.     java.awt.List list1  = new java.awt.List(9);//显示在线用户信息   
  34.     Socket socket = null;//连接端口  
  35.     PrintStream ps = null;//输出流  
  36.     Listen listen = null;  
  37.     //监听线程类  
  38.     class Listen extends Thread {  
  39.         BufferedReader reader;  
  40.         PrintStream ps;  
  41.         String cname;  
  42.         Socket socket;  
  43.         ChatClient chatClient;  
  44.         public Listen(ChatClient client,String name,Socket socket) {  
  45.             try {  
  46.                 this.chatClient = client;  
  47.                  this.socket = socket;  
  48.                  this.cname = name;  
  49.                  reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  50.                  ps = new PrintStream(socket.getOutputStream());  
  51.             } catch (IOException e) {  
  52.                 e.printStackTrace();  
  53.             }  
  54.         }  
  55.         public void run() {  
  56.             while (true) {  
  57.                 String line=null ;  
  58.                 try {  
  59.                 line = reader.readLine(); //读取数据流  
  60.                 System.out.println("客户端:"+line);  
  61.                   
  62.             }catch (IOException ex) {  
  63.                 ex.printStackTrace();  
  64.                 ps.println("quit");; //断开连接  
  65.                 return;  
  66.             }  
  67.             StringTokenizer stinfo = new StringTokenizer(line,":"); //分解字符串  
  68.             String keyword = stinfo.nextToken();  
  69.             if (keyword.equals("MSG")) {  
  70.                 chatClient.tfChat.append(line+"\n");  
  71.             }  
  72.             else if (keyword.equals("newUser")){  
  73.                 chatClient.list1.clear();  
  74.                 chatClient.list1.add("users"0);  
  75.                 int i = 1;  
  76.                 while (stinfo.hasMoreTokens()) {  
  77.                     chatClient.list1.add(stinfo.nextToken(), i++);  
  78.                 }  
  79.             }  
  80.         }  
  81.           
  82.       }  
  83.     }  
  84.     public void actionPerformed(ActionEvent e) {  
  85.         try{  
  86.             if(e.getSource()==btConnect) { //点击连接按钮  
  87.                 if (socket == null) {  
  88.                     socket = new Socket(InetAddress.getLocalHost(),5566);//实例化一个套接字  
  89.                     ps = new PrintStream(socket.getOutputStream());//获取输出流,写入信息  
  90.                     StringBuffer info = new StringBuffer("info:");  
  91.                     String userinfo = tfName.getText()+":"+InetAddress.getLocalHost().toString();  
  92.                     ps.println(info.append(userinfo));//输出信息  
  93.                     ps.flush();  
  94.                     listen = new Listen(this,tfName.getText(),socket);  
  95.                     listen.start();  
  96.                 }  
  97.             } else if (e.getSource() == btDisconnect) { //点击断开连接按钮  
  98.                 disconnect();  
  99.             } else if (e.getSource() == btSend) { //点击发送按钮  
  100.                 if (socket != null) {  
  101.                     StringBuffer msg = new StringBuffer("MSG:");  
  102.                     String msgtxt = new String(tfMessage.getText());  
  103.                     ps.println(msg.append(msgtxt));//发送信息  
  104.                     ps.flush();  
  105.                 } else {  
  106.                     JOptionPane.showMessageDialog(this"请先连接!""提示"1);  
  107.                 }  
  108.             }  
  109.               
  110.         } catch (Exception ex) {  
  111.             ex.printStackTrace();//输出错误信息  
  112.         }  
  113.     }  
  114.     public void disconnect() { //断开连接方法  
  115.         if (socket != null) {  
  116.             ps.println("quit");//发送信息  
  117.             ps.flush();  
  118.               
  119.             socket = null;  
  120.             tfName.setText("");  
  121.         }  
  122.     }  
  123.       
  124.       
  125.       
  126.       
  127.       
  128.       
  129.   
  130.       
  131.     public ChatClient(Socket socket) {  
  132.           
  133.           
  134.         this.setLayout(new BorderLayout());  
  135.           
  136.         JPanel panel1 = new JPanel();  
  137.         Label label = new Label("姓名");  
  138.         panel1.setBackground(Color.orange);  
  139.         panel1.add(label);  
  140.         panel1.add(tfName);  
  141.         panel1.add(btConnect);  
  142.         panel1.add(btDisconnect);  
  143.         this.add(panel1,BorderLayout.NORTH);  
  144.           
  145.         JPanel panel2 = new JPanel();  
  146.         panel2.add(tfChat);  
  147.         panel2.add(list1);  
  148.         this.add(panel2,BorderLayout.CENTER);  
  149.           
  150.         JPanel panel3 = new JPanel();  
  151.         Label label2 = new Label("聊天信息");  
  152.         panel3.add(label2);  
  153.         panel3.add(tfMessage);  
  154.         panel3.add(btSend);  
  155.         this.add(panel3,BorderLayout.SOUTH);  
  156.           
  157.         this.setBounds(50,50,400,350);  
  158.         this.setVisible(true);  
  159.           
  160.         btConnect.addActionListener(this);  
  161.         btDisconnect.addActionListener(this);  
  162.         btSend.addActionListener(this);  
  163.           
  164.     }  
  165.       
  166.     /** 
  167.      * @param args 
  168.      */  
  169.     public static void main(String[] args) {  
  170.         ChatClient client = new ChatClient(new Socket());  
  171.         System.out.println(client.socket);  
  172.     }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值