使用ServerSocket和Socke对象t建立简单的套接字(Socket)通信。
1.在C/S通信模式中, Server端需要创建监听端口的 ServerSocket,负责接收客户连接请求。
以下是通信的服务器端程序:
- package Server1;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class Server1 {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- ServerSocket serverSocket=null;
- //创建一个ServerSocket对象
- Socket socket=null;
- //创建一个socket对象
- BufferedReader sockIn;
- PrintWriter sockOut;
- //创建输入输出对象
- BufferedReader stdIn=new BufferedReader(new InputStreamReader(System.in));
- //使用BufferedReader包裹输入流对象,获得输入字段。
- try{
- serverSocket=new ServerSocket(8888);
- //这里创建了一个端口号为8888的ServerSocket,ServerSocket是服务器Socket,
- //可以用来侦听连接,为每个新建立的连接都创建一个Socket对象.
- System.out.println("server listening on port 8888");
- socket=serverSocket.accept();
- //调用ServerSocket的accept()方法,会返回一个socket,保存在已经声明的socket中,这个socket就代表这次连接
- if(socket==null){
- //判断sockt是否为空
- System.out.println("socket is null");
- System.exit(1);
- }
- System.out.println("accept connection from:"+socket.getInetAddress().getHostAddress());
- //socket代表这次连接,可以取IP地址
- sockIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
- //创建输入流,可以使用这个对象接收Client发来的数据
- sockOut=new PrintWriter(socket.getOutputStream());
- //创建输出流,可以使用这个对象向Client发送数据
- sockOut.println("hello I am server");
- //使用sockOut对象发送信息
- sockOut.flush();
- //在使用缓冲区传输数据时,添加flush强制发送数据,不必等缓冲区慢,防止小数据无法传输
- String s=sockIn.readLine();
- //使用sockIn读取接收的数据
- System.out.println("Server received:"+s);
- sockOut.close();
- sockIn.close();
- socket.close();
- serverSocket.close();
- }catch(Exception e){
- System.out.println(e.toString());
- System.out.println("server exit");
- }
- }
- }
以下是Client客户端的代码,为方便测试,直接使用127.0.0.1作为服务器地址。
- package Client1;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.Socket;
- public class Client1 {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Socket socket=null;
- BufferedReader sockIn;
- PrintWriter sockOut;
- try{
- socket=new Socket("127.0.0.1",8888);
- //建立socket连接,连接本机地址,8888端口
- if(socket==null){
- //判断是否连接
- System.out.println("socket null,connection error");
- System.exit(1);
- }
- System.out.println("conected to server");
- sockIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
- sockOut=new PrintWriter(socket.getOutputStream());
- //创建输入输出流,这时的sockIn已经从socket中接收到数据
- sockOut.println("hello,I am client");
- //使用sockOut发送数据
- sockOut.flush();
- String s=sockIn.readLine();
- System.out.println("Client recived:"+s);
- sockOut.close();
- sockIn.close();
- socket.close();
- }catch(Exception e){
- System.out.println(e.toString());
- System.out.println("client exit");
- }
- }
- }
3.socket通信的本地测试。
由于在eclipse中难以测试通信,需要使用cmd进行测试,在使用cmd测试时,需要注意运行时包的问题。
网上有说法在eclipse中 窗口->新建窗口 可以多窗口测试,本人实测无效,两个窗口公用一个控制台,无法显示预期结果(如有问题,欢迎指正)。
以作者的路径为例,我的.JAVA文件在C:\Users\lenovo\workspace\ch16\src\Client1\Client1.java
使用该地址编译是可以通过的,但是无法运行,会报错,
Exception in thread "main" java.lang.NoClassDefFoundError
如图:
这是由于包嵌套的原因,应该使用如下的关系编译,程序运行结果如图: