Java网络编程:服务器端和客户端互发信息
引言
为了学习Java网络编程,用一个QQ(屌丝版)作为例子练手,记录屌丝版QQ的开发过程,这里我们认为已经掌握其中的网络基础部分,即HTTP协议,TCP/IP协议等,在此基础上我们开始我们的Java网络部分的学习,我们要知道服务器和客户端是如何通信的,首先我们要了解Java网络知识中的一个很重要的东西——Socket
Socket初探
ServerSocket和Socket
首先服务器端需要用到java.net包下的ServerSocket类,该类的一个实例用于监听等待客户端的连接,而客户端需要用到net包下的Socket类,用于向服务器端发送连接请求,客户端是怎样与服务器端建立连接的呢,首先客户端的Socket实例要制定服务器端的ip地址和端口,服务器端如何与客户端建立连接呢,服务器端的ServerSocket类的accept一直在监听等待客户端发来的连接请求,如果没有收到,则一直阻塞在accept这句代码这儿(可以在Socket s=ss.accept();这行代码后面打印出一句语句,可以发现,程序并不会执行到这行代码),以下代码1说明服务器端ServerSocket的用法,代码2说明客户端Socket的用法
代码1
创建一个类,名字叫Server,在类的构造函数中创建ServerSocket等实例
public class MyServer1 {
public MyServer1()
{
//在9999号端口监听
ServerSocket ss=new ServerSocket(9999);
//等待某个客户端来连接,该函数会返回一个Scoket连接
Socket s=ss.accept();
}
}
代码2
创建一个类,名字叫Client
public class MyClient1 {
public MyClient1()
{
//Socket,就是连接某个服务器端,127.0.0.1表示服务器的Ip 9999表示端口号
Socket s=new Socket("127.0.0.1", 9999);
}
}
服务器和客户端互发信息
服务器端和客户端是如何发送信息的呢,用到的还是java.io包下的东西,服务器端要读取客户端发来的信息,用到InputStreamReader,BufferedReader,其中InputStreamReader的输入为Socket.getInputStream()方法返回的输入流,要发送信息给客户端用到PrintWriter,其中PrintWriter的输入为Socket.getOutputStream()方法返回的输出流,具体用法如下
客户端发送信息
//如果s连接成功,就可以发数据给服务器
//我们通过pw向s写数据 true表示刷新流
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
pw.println("Hello Server,I'm Client");
服务器端接受信息
//要读取s中传递的数据
InputStreamReader isr=new InputStreamReader(s.getInputStream());
BufferedReader br=new BufferedReader (isr);
//行读取
String info=br.readLine();
System.out.println("服务器收到的信息是,"+info);
然后服务器端向客户端发送信息
PrintWriter pw=new PrintWriter(s.getOutputStream(), true);
pw.println("Hello Client,I'm Server");
然后客户端收到服务器端的信息
InputStreamReader isr=new InputStreamReader(s.getInputStream());
BufferedReader br=new BufferedReader (isr);
//行读取
String response=br.readLine();
System.out.println("客户端收到的信息是,"+response);
服务器和客户端互发信息(从控制台输入)
之前服务器和客户端互发的信息是写死在pw.println里,我们稍微修改一下,从控制台输入
之前建立连接的方式相同,而且读取和发送信息的方式也类似,只是多了一个需要从控制台输入信息
服务器端代码
比如服务器端接受客户端发来的信息依旧不变,从Socket.getInputStream()方法返回的输入流作为InputStreamReader的输入
但服务器端还需要一个InputStreamReader接受从System.in传进来的输入用来接收从控制台输入的想发送给客户端的信息
//接受客户端发来的信息
InputStreamReader isr=new InputStreamReader(s.getInputStream());
BufferedReader br=new BufferedReader(isr);
//打印客户端发来的信息
String infoFromClient=br.readLine();
System.out.println("客户端发来"+infoFromClient);
//接收从控制台输入的信息
InputStreamReader isr2=new InputStreamReader(System.in);
BufferedReader br2=new BufferedReader(isr2);
//打印从控制台输入的信息
System.out.println("输入要发送给客户端的信息");
String response=br2.readLine();
客户端的代码
而客户端代码也类似
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
InputStreamReader isr2=new InputStreamReader(s.getInputStream());
BufferedReader br2=new BufferedReader(isr2);
服务器和客户端互发信息(从聊天窗口输入)
有了第一个的基础,这一部分就只是将从控制台输入变成了从JTextArea域里读取文字,这里我们暂且认为已有Java界面的基础,对JFrame了解
这一部分我们希望客户端发来的消息显示在聊天窗口中,而不是控制台,那么将
System.out.println("客户端发来"+infoFromClient);替代为jta.append("客户端发来"+info+"\r\n");即可
另外我们希望客户端发给服务器的消息也从聊天窗口输入,那么我们需要继承ActionListener,实现当点击发送按钮时,读取JTextField域的文字,具体实现如下
String info=jtf.getText();
pw.println(info);
//清空发送框的内容
jtf.setText("");