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.服务器端继续等待新的连接。

首先是服务端代码:

package ChatTwoPackage;    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+"\r\n");   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()+"\n");   text_se.setText("");  }//按下发送按钮后,将内容发出,并更新自己聊天框的内容  if(ev.getActionCommand().equals("下线"))  {   text_re.append("你已下线\n");   this.cout.println(name+"离线\n"+"bye\n");   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地址和端口     }    } 运行效果: JAVA-hello/hi的简单的网络聊天程序

 

 

         
上一篇:微信小程序 单选按钮 最佳


下一篇:Python 3.9 新特性:任意表达式可作为装饰器!