一、     简单网络对话程序

设计任务:客户端向服务器发送一字符串,并能读取服务器返回的字符串。

知识点:TCP套接字技术,C/S软件架构程序设计

重点理解:Java客户套接字类Socket和服务器套接字类ServerSocket,

        以及字符串读/写类BuffferedReader/PrintWriter。

 

   在C/S软件架构程序设计技术中,实现网络通信的两个应用进程,一个叫做服务进程,另一个叫做客户进程,如图2.1所示。服务进程首先被动打开一个监听端口,如8008,客户进程主动访问这个端口,完成对话聊天前的TCP三次握手连接。

java编写简单聊天室 java聊天程序设计代码_套接字类Socket

 

图2.1 TCP连接建立的过程

 

   在Java网络程序设计中,有两个套接字类:服务进程中的是ServerSocket类,客户进程中的是Socket类。

   服务进程首先开启一个或多个监听端口,客户进程向服务进程发起TCP三次握手连接,分别见附录1、2中的代码。

   TCP连接成功后,逻辑上可理解如图2.2所示,通信进程的双方具有两个流(输出流和输入流)。逻辑上可将两个流理解为两个通信管道的全双工通信模式,一个用于向对方发送数据,另一个用于接收对方的数据。

  

   套接字类有两个基本的方法可以获得两个通信管道的入口:

 

     Socket.getInputStream()方法可获得输入字节流的入口地址;

     Socket.getOutputStream()方法可获得输出字节流的出口地址;

java编写简单聊天室 java聊天程序设计代码_互联网程序设计_02


功能详细描述: 图2.2 TCP连接成功后的两条逻辑通道

   客户端程序1:TCPClient.java具有网络接收和发送能力的程序。

   客户端程序2:TCPClientJFrame.java为界面模块。

   服务器程序:TCPServer.java具有网络接收和发送功能。

 

   网络对话方式是:

     客户端程序发送一条信息给服务器TCPServer.java,服务器接收并回送该信息到客户端,客户端接收并显示该信息。

 

1、程序设计第一步:

  新建一个程序包,建议命名为socketTCP;

   制作并运行TCPServer程序,通过命令行窗口(netstat -an)察看是否已开启8008监听端口。

package socketTCP;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class TCPServer {
  private int port=8000;

  private ServerSocket serverSocket;//服务器套接字。

 

  public TCPServer() throws IOException {

    serverSocket = new ServerSocket(8000);//开启8008号监听端口。

    System.out.println("服务器启动");

  }

 

  private PrintWriter putWriter(Socket socket)throws IOException{

    OutputStream socketOut = socket.getOutputStream();//获得输出流缓冲区的地址。

    return new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true);

 

  }

  private BufferedReader getReader(Socket socket)throws IOException{

    InputStream socketIn = socket.getInputStream();//获得输入流缓冲区的地址

    return new BufferedReader(new InputStreamReader(socketIn,"GB2312"));

  }


  public void service() {//单客户版本,即每次只能同时和一个客户建立通信连接。

    while (true) {

      Socket socket=null;

      try {

     socket = serverSocket.accept();

         //阻塞语句,监听并等待客户发起连接,有连接请求就生成一个套接字。

     System.out.println("New income: "+socket.getInetAddress());

        //本地服务器观测台显示请求的用户信息。

        BufferedReader br =getReader(socket);//定义字符串输入流。

        PrintWriter pw = putWriter(socket);//定义字符串输出流。


        String msg;

        while ((msg = br.readLine())!= null) //阻塞语句,从输入流中读入一行字符串。

         {
             System.out.println("来自用户:"+msg);

             pw.println("来自服务器:"+msg);//向输出流中输出一行字符串。
            
             System.out.println(msg);
            
             //pw.println("来自服务器2:"+msg);

             if (msg.equals("bye")) //如果客户发送的消息为“bye”,就结束通信

              break;

        }

      }catch (IOException e) {

         e.printStackTrace();

      }finally {

         try{

           if(socket!=null)

               socket.close();  //断开连接

         }catch (IOException e) {e.printStackTrace();}

      }

    }

  }

 

  public static void main(String args[])throws IOException {

    new TCPServer().service();

  }
    
}

   TCPServer的运行问题,TCPServer只能运行一次,且自身不能终止运行,要终止它运行,需要点击“运行”、“停止构建”。

2、 程序设计第二步:

 制作并理解TCPCilent.java程序;

java编写简单聊天室 java聊天程序设计代码_互联网程序设计_03

package socketTCP;

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

public class TCPClient {
    //套接字程序设计. 

  private Socket socket=null;

  //用于字节和字符之间转换用的变量.

  private PrintWriter pw;

  private BufferedReader br;

  public TCPClient(String ip,String port) throws IOException{

    socket=new Socket(ip,Integer.parseInt(port));
     //定义对象构造方法
     //主动向服务器发起连接,实现TCP中三次握手的过程。

     //若不成功(网络问题,地址错误,服务器资源紧张等),抛出错误,其错误信息交由调用者处理。

     //若成功,做下面两件事情。   

     //Socket连接成功后,通过调用GET方法,可获得字节输出流和字节输入流,输出流用于发送信息,输入流用于接收信息。

     OutputStream socketOut = socket.getOutputStream();

     pw=new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true);

     //得到网络输出字节流地址,并装饰成网络输出字符流

     InputStream socketIn = socket.getInputStream();

     br=new BufferedReader(new InputStreamReader(socketIn,"GB2312"));

     //得到网络输入字节流地址,并装饰成网络输入字符流

  }
  public void send(String msg){

        pw.println(msg);
        //定义网络信息发送方法供外部调用
        //输出字符流,由Socket调用系统底层函数,经网卡发送字节流。

   }
  public String receive(){
//定义网络信息接收方法供外部调用
   String msg;

      try {

          msg = br.readLine();//接收一行信息,阻塞语句。

      //从网络输入字符流中读信息,每次只能接收一行信息.

      //若不够一行(无行结束符),该语句阻塞(阻塞语句),直到条件满足,程序才往下运行

      } catch (IOException ex) { msg=null;  }

    return msg;

  }
  public void close() {
//定义网络连接关闭方法供外部调用
     try {
      if(socket!=null) 

         socket.close();//实现四次握手断开.

    } catch (IOException ex) {  }

  }

   //模块内测试与运行,需先运行TCPServer。

  public static void main(String args[]) throws IOException{

    TCPClient tc=new TCPClient("127.0.0.1","8000");

    tc.send("123456789");//发送一行字符串

    System.out.println(tc.receive());//接收一行字符串并在屏幕上显示

    tc.close();     

  }
}

3、 程序设计第三步:

   制作TCPClientJFrame.java主程序界面模块;

在“连接”按钮中设置如下动作:

String ip=jTextField2.getText();
    String port=jTextField3.getText();
    try {
        ec=new TCPClient(ip,port);
        jTextArea1.append("服务器连接成功.\r\n");
    } catch (IOException ex) {
       jTextArea1.append("服务器连接失败.\r\n");
    }

 

在“发送”按钮中添加网络发送和接收方法:

String msg1=jTextField1.getText();  
    ec.send(msg1);//发送一串字符。
    String msg2=ec.receive(); //接收一行字符串。
    jTextArea1.append(msg2);

 

程序截图:

 

java编写简单聊天室 java聊天程序设计代码_TCP_04

java编写简单聊天室 java聊天程序设计代码_java编写简单聊天室_05