zoukankan      html  css  js  c++  java
  • JAVA-hello/hi的简单的网络聊天程序

     

    使用Tcp协议的Socket编程主要用到两个类,Socket和ServerSocket。ServerSocket本身也是一个Socket,只是它同时包含了一些额外的服务器终端的功能,比如监听端口,等待客户端Socket前来建立连接等。通过accept方法一旦和客户端建立起连接,就会返回一个普通的Socket和客户端Socket进行对等的通信。

    本文的Demo实现的功能很简单,用户输入消息,发送给服务器,服务器原封不动返回给客户端。原理是:启动一个服务器线程和两个客户端线程。服务器线程监听2000端口,等待客户端进程的连接。客户端线程包括一个发送线程和一个接收线程,发送线程连接服务器的2000端口,将用户输入的消息发送给服务器线程,接收线程监听2001端口,等待服务器返回的数据。服务器通过2000端口收到客户端发来的数据后,将数据原封不动发送到客户端的2001端口,完成通信。

    所谓socket 通常也称作”套接字“,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。

    以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

    重要的Socket API

    java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。

    Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。
    getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。
    getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。
    注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

    TCP 编程

    服务器端套路

    1.创建ServerSocket对象,绑定监听端口。
    2.通过accept()方法监听客户端请求。
    3.连接建立后,通过输入流读取客户端发送的请求信息。
    4.通过输出流向客户端发送响应信息。
    5.关闭响应的资源。

    客户端套路

    1.创建Socket对象,指明需要连接的服务器的地址和端口号。
    2.连接建立后,通过输出流向服务器发送请求信息。
    3.通过输入流获取服务器响应的信息。
    4.关闭相应资源。

    多线程实现服务器与多客户端之间通信步骤

    1.服务器端创建ServerSocket,循环调用accept()等待客户端连接。
    2.客户端创建一个socket并请求和服务器端连接。
    3.服务器端接受客户端请求,创建socket与该客户建立专线连接。
    4.建立连接的两个socket在一个单独的线程上对话。
    5.服务器端继续等待新的连接。

    首先是服务端代码:

    import java.io.*;
    import java.net.*;
      
    public class ChatTwoServer {
      
     public ChatTwoServer(int port,String name) throws IOException
     {
     ServerSocket server=new ServerSocket(port);//创建seversocket对象,提供tcp连接服务。指定端口port,等待tcp连接。
     System.out.print("正在等待连接,请勿操作!");
     Socket client=server.accept();//创建socket对象,它等待接收客户端的连接。
     new ChatTwoClient(name,client);//实现图形界面。
     server.close();
     }
      
     public static void main(String[] args) throws IOException {
     new ChatTwoServer(2001,"SQ");
      
     }
      
    }
    

      

    然后是客户端的代码:
    package ChatTwoPackage;
      
    import java.awt.event.*;
    import javax.swing.*;
    import java.net.*;
    import java.io.*;
      
    public class ChatTwoClient extends JFrame implements ActionListener {
     private String name;
     private JTextArea text_re;
     private JTextField text_se;
     private PrintWriter cout;
     private JButton buttons[];
     public ChatTwoClient(String name,Socket socket) throws IOException
     {
     super("我:"+name+InetAddress.getLocalHost().getHostAddress()+":"+socket.getLocalPort());
     this.setBounds(320, 240, 400, 240);
     this.text_re=new JTextArea();
     this.text_re.setEditable(false);
     this.getContentPane().add(new JScrollPane(this.text_re));
      
     JToolBar toolBar=new JToolBar();
     this.getContentPane().add(toolBar,"South");
     toolBar.add(this.text_se=new JTextField(30));
     buttons=new JButton[2];
     buttons[0]=new JButton("发送");
     buttons[1]=new JButton("下线");
     toolBar.add(buttons[0]);
     toolBar.add(buttons[1]);
     buttons[0].addActionListener(this);
     buttons[1].addActionListener(this);//给按钮添加事件监听,委托当前对象处理
     this.setVisible(true);
     this.name=name;
     this.cout=new PrintWriter(socket.getOutputStream(),true);//获得socket输出流
     this.cout.println(name);
     BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); //将socket的字节输入流转换为字符流,默认GBK字符集,再创建缓冲字符输入流
            String line="连接"+br.readLine()+"成功";
            while(line!=null&&!line.endsWith("bye"))
     {
      text_re.append(line+"
    ");
      line=br.readLine();
     }//读取对方发送的内容并显示,直到内容为为空或对方下线
     br.close();
     this.cout.close();
     socket.close();
     buttons[0].setEnabled(false);
     buttons[1].setEnabled(false);
     }
     public ChatTwoClient(String name,String host,int port) throws IOException
     {
     this(name,new Socket(host,port));//调用另一个构造方法
     }
     public void actionPerformed(ActionEvent ev)
     {
     if(ev.getActionCommand().equals("发送"))
     {
      this.cout.println(name+":"+text_se.getText());
      text_re.append("我:"+text_se.getText()+"
    ");
      text_se.setText("");
     }//按下发送按钮后,将内容发出,并更新自己聊天框的内容
     if(ev.getActionCommand().equals("下线"))
     {
      text_re.append("你已下线
    ");
      this.cout.println(name+"离线
    "+"bye
    ");
      buttons[0].setEnabled(false);
      buttons[1].setEnabled(false);
     }//下线按钮按下后,发送bye作为下线标记
     }
      
      
     public static void main(String[] args) throws IOException {
     new ChatTwoClient("mxl","127.0.0.1",2001); //ip地址和端口
      
     }
      
    }
    

      

    运行效果:
     
     
     
     
     
  • 相关阅读:
    Fire
    Apple Tree
    访问艺术馆
    三角关系
    字母表
    折纸
    旅行
    单词分类

    圆桌游戏
  • 原文地址:https://www.cnblogs.com/xqqu/p/12005773.html
Copyright © 2011-2022 走看看