JAVA网络编程 ——基于TCP的Socket编程—实现服务器端与客户端的实时对话

一,HTTP与Socket

1.HTTP:超文本传输协议

特点:客户端发送的请求需要服务器端每次来响应,在请求结束之后主动释放连接,从建立连接到关闭连接称为“一次连接”,所以HTTP是“短连接”。

2.Socket(IP+PORT):是TCP/IP的封装与应用,它不是协议,而是API

特点:客户端与服务器之间一旦建立连接,就可以互相范松消息,也叫对话,但在实际应用中,通信双方经过许多的中间节点,比如,路由器,网关,防火墙,大部分防火墙会默认关闭长时间处于不活跃的状态连接,而是Socket断开。

选择:当服务器主要想客户端推送消息,为了保持客户端与服务器数据的实时与同步,通常会从采用HTTP协议,只要客户端定时向服务器端发送请求,同时也是在询问是否有新的数据,如果有那就传入客户端。

二,TCP/IP模型

1.通信原理图

 

2.模型图

                                                             

三,基于TCP的网络编程

1.Socket: IP地址+端口号组成了Socket,Socket是网络上运行程序之间双向通信的终结点,是TCP和UDP的基础。

2.JAVA提供的网络功能(可以查看API)

InetAddress:标识IP地址

URL:统一资源定位,通过URL可以直接读取或写入网络上的数据

Sockets:使用TCP协议实现Socket相关的类

Datagram:使用UDP协议。将数据保存在数据包中,通过网络通信。

3.Socket通信模型

 

4.代码(可直接粘贴复制,使用)请修改包名

1.服务器端线程类   ServerThread.class

//*******************服务器端线程类********************//
package com.NullChenHui;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
 
public class ServerThread extends Thread {
    private int port;
    private boolean OVER_FLAG = false;
    public ServerThread(int port) {
        this.port = port;
    }
 
    @Override
    public void run() {
        // TODO Auto-generated method stub
        /**
         * 使用无线循环或者有限循环来实现客户端与服务器的对话
         */
        try {
            //1.创建连接服务器的Socket 并绑定端口号
            ServerSocket ssocket = new ServerSocket(port);
            while(!OVER_FLAG) {
            //2.监听来自客户端的请求   并返回Socket实例
            Socket socket = ssocket.accept();
            //3.获取输入流  
            InputStream is = socket.getInputStream();  
            InputStreamReader  isr = new InputStreamReader(is);  //字节流包装为字符流
            BufferedReader bf = new BufferedReader(isr);   //添加进缓存
            //4.从缓存中读取数据
            String info = null;
            if("OVER".equals(info)) {
                OVER_FLAG = true;
                break;
            }
            while((info=bf.readLine()) != null) {
                System.out.println("客户端说:"+info);
                if("OVER".equals(info)) {
                    OVER_FLAG = true;
                    break;
                }
            }
            
            
            socket.shutdownInput();
            String data = null;
            System.out.print("服务端:");
            Scanner scanner = new Scanner(System.in);
            String data1 = scanner.nextLine();
            
            //回馈给客户端
            OutputStream os = socket.getOutputStream();
             PrintWriter pw = new PrintWriter(os);
            //3.发送数据
            pw.write(data1);
            pw.flush();
            //4.关闭资源
            os.close();
            pw.close();
            is.close();
            bf.close();
//            socket.shutdownOutput();
            }
            System.out.println("对话结束");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

2.服务器端主程序  MyServerSocket.class

package com.NullChenHui;
/**
 * 基于TCP的Socket的编程    服务端
 * @author NullChen
 *
 */
public class MyServerSocket{
    
    @SuppressWarnings("resource")
    public static void main(String[] args) {
        System.out.println("***我是服务器***");
        ServerThread sThread = new ServerThread(3333);
        sThread.start();
    }
}

3.客户端线程类 ClientThread.class

package com.NullChenHui;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
 
public class ClientThread extends Thread {
    private String IP;
    private int port;
    private boolean OVER_FLAG = false;
    public ClientThread(String IP ,int port) {
        this.IP = IP;
        this.port = port;
    }
 
    @Override
    public void run() {
        // TODO Auto-generated method stub
        OutputStream os =null;
        PrintWriter pw = null;
        
        try {
            //1.建立客户端Socket  并指定发送服务器端的地址(IP + port )
            
            //2.获取输出流
             
            while(!OVER_FLAG) {
             Socket socket = new Socket(IP,port);
             os = socket.getOutputStream();
             pw = new PrintWriter(os);
            //3.发送数据
            
            System.out.print("客户端:");
            Scanner scanner = new Scanner(System.in);
            String data1 = scanner.nextLine();
         
            pw.write(data1);
            pw.flush();
            //4.关闭资源
            socket.shutdownOutput();    
            //接受来自服务器的反馈
            InputStream is = socket.getInputStream();  
            InputStreamReader  isr = new InputStreamReader(is);  //字节流包装为字符流
            BufferedReader bf = new BufferedReader(isr);   //添加进缓存
            //4.从缓存中读取数据
            String info = null;
            while((info=bf.readLine()) != null) {
                System.out.println("服务器说:"+info);
                if("OVER".equals(info)) {
                    OVER_FLAG = true;
                    break;
                }
            }
              
            /***
             * 如果获取的内容是空的 说明服务器端还没有发送数据
             */
 
            // 5 关闭资源
            os.close();
            pw.close();
            is.close();
            bf.close();
//            socket.shutdownInput();
        }
            System.out.println("对话结束");
            
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

4.客户端主程序 MyClientSocket.class

package com.NullChenHui;
 
public class MyClientSocket{
    public static void main(String[] args) {
        System.out.println("***我是客户端***");
        ClientThread cThread = new ClientThread("127.0.0.1",3333);
        cThread.start();
 
    }
}

四,注意问题

1.先启动服务器端后启动客户端

2.两个之间的对话就是客户端说一句,服务器说一句。

3.以客户端以OVER结束对话

4.在关闭输入输出流的地方有点小问题。

五,java调用tcp socket接口

package com.autotest.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class SocketUtil {

 /*
  * 获取socket连接
  */
    public static Socket getConnection(String ip, int port) {
        Socket socket = null;
        try {
            socket = new Socket(ip, port);
            socket.setSoTimeout(30000);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return socket;
    }

    /*
     * 发送报文
     */
    public static String send(Socket socket, String cmd) {
        InputStream in = null;
        OutputStream out = null;
        BufferedReader br = null;
        try {
            // in代表服务器到客户端的流
            in = socket.getInputStream();
            // 代表客户端到服务器的流
            out = socket.getOutputStream();

            // 输入执行命令
            PrintWriter printWriter = new PrintWriter(out, true);
            printWriter.println(cmd);
            printWriter.flush();

            // 接收执行命令结果
            br = new BufferedReader(new InputStreamReader(in));
            return br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /*
     * 关闭socket连接
     */
    public static void close(Socket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    /*
     * 测试代码
     */
    public static void main(String args[]){
  String result="";
  Socket socket=null;
  String cmd="New 100004341413830 ";
  try {
   socket=SocketUtil.getConnection("192.168.1.100", 10000);
   String resultStr=SocketUtil.send(socket, cmd);
   String resultArr[]=resultStr.split(" ");
   resultStr=resultArr[1].substring(1, resultArr[1].length()-1);
   if("OK".equals(resultStr)){
    result="成功";
   }else {
    result="失败";
   }
   System.out.println(result);
  } catch (Exception e) {
   SocketUtil.close(socket);
  }
    }

}

 

posted @ 2018-11-26 10:04  烟雨观春柳  阅读(585)  评论(0)    收藏  举报