Java中基于Socket的TCP编程

TCP编程

         1)需要建立连接通道
        2)数据大小无限制

        3)可靠连接---->执行效率低

三次握手

第一次握手:建立连接
第二次握手:服务器收到syn包
第三次握手:服务器给反馈
完成三次握手之后服务器与客户端才会建立连接

用到的类和类的方法

Socket类

此类实现客户端套接字(也可以就叫“套接字”)。

构造方法
public Socket(InetAddress address, int port) throws IOException
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
 
public Socket(String host, int port) throws UnknownHostException,IOException
创建客户端套接字对象,并且指定端口号和ip文本形式

public ServerSocket(int port) throws IOException
创建绑定到特定端口的服务器套接字

使用的方法
public OutputStream getOutputStream() throws IOException
返回此套接字的输出流。

public InputStream getInputStream()throws IOException
返回此套接字的输入流。

public InetAddress getInetAddress()

返回套接字连接的地址。

public void shutdownOutput() throws IOException
禁用此套接字的输出流。

ServerSocket类

此类实现服务器套接字。

构造方法
public ServerSocket(int port) throws IOException
创建绑定到特定端口的服务器套接字。端口 0 在所有空闲端口上创建套接字。

使用到的方法
public Socket accept() throws IOException
侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。  

TCP(建立连接通道)编程的客户端的开发步骤

  1)创建客户端的Socket对象
 2)获取通道内的输出流对象
 3)给服务器端写数据
 4)释放资源

注意:先运行客户端会报错:java.net.ConnectException: Connection refused: connect 连接被拒绝
          不要先运行客户端,客户端的连接需要服务器监听到才能连接

 
public class ClientDemo {

    public static void main(String[] args) throws Exception {
        //1)创建客户端的Socket对象
        Socket s = new Socket("192.168.10.1", 12306) ;
        //2)获取通道内的输出流对象
        OutputStream out = s.getOutputStream() ;
        //3)给服务器端写数据 过去
        out.write("hello,Tcp,我来了".getBytes());        
        //4)释放资源
        s.close();
    }
}

TCP编程的服务端的开发步骤:

 1)创建服务器端的Socket对象
 2)监听客户端的连接(阻塞方法)
 3)获取通道内的输入流
 4)读取数据,显示控制台
 5)释放资源

 
注意:多次运行服务器端会报错:java.net.BindException: Address already in use: JVM_Bind  地址被绑定,因为已经有服务器在监听客户端连接
 
public class ServerDemo {
    
    public static void main(String[] args) throws Exception {
        //1)创建服务器端的Socket对象        
        ServerSocket ss = new ServerSocket(12306) ;                
         //2)监听客户端的连接(阻塞方法)
        Socket s = ss.accept() ;
         //3)获取通道内的输入流        
        InputStream in = s.getInputStream() ;
         //4)读取数据,显示控制台
        //获取ip文本形式'
        String ip = s.getInetAddress().getHostAddress() ;
        byte[] bys = new byte[1024] ;
        int len = in.read(bys) ;
        String data = new String(bys, 0, len) ;
        System.out.println("from" +ip +"data is :"+data);
         //5)释放资源
        s.close();
        ss.close(); 服务端可以不关闭
        
    }
}

需求:

客户端将文本文件中的数据,复制到服务器端输出的新的java文件中,然后服务器端要给客户端反馈数据,客户端将反馈的数据展示

在其中出现了一个问题:

在客户端这边,如果SendDemo.java如果读完了,服务器端那边并不知道是否读完(流是不能使用null作为信息结束条件的,但是客户端文本文件是可以用null作为信息结束条件的)。

解决方案:

      1)客户端这边,写一个结束条件,---->服务器如果读取到了这个结束条件的话,服务器就可以反馈
               第一种方式虽然可以解决这种问题,不好,不灵活!
      2)public void shutdownOutput():通知服务器端

客户端程序

public static void main(String[] args) throws IOException {        
    //创建客户端的Socket对象
    Socket s = new Socket("192.168.10.1",11111); //当前对象创建之后,就会和服务器端建立连接通道    
    //封装文本文件
    BufferedReader br = new BufferedReader(new FileReader("SendDemo.java")) ;    
    //封装通道内的流
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;
    //读写操作
    String line =null;
    while((line=br.readLine())!=null) {
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
        
    //自定义的结束条件
    /*bw.write("over");
    bw.newLine();
    bw.flush();*/    
    //通知服务器端,客户端的文件已经完了,赶紧给反馈
    s.shutdownOutput();
    //获取服务器反馈的数据
    //获取通道内的字符输入流
    BufferedReader brClient = new BufferedReader(
            new InputStreamReader(s.getInputStream())) ;
    String client = brClient.readLine() ;
    System.out.println(client);
    //释放资源
    br.close();
    s.close();            
}
服务器端程序
public static void main(String[] args) throws IOException {
    //服务器端的Socket对象
    ServerSocket ss = new ServerSocket(11111) ;
    //监听
    Socket s = ss.accept() ;
    //封装通道内的流
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;
    //封装最终要输出的文本文件
    BufferedWriter bw= new BufferedWriter(new FileWriter("Copy.java")) ;
    String line = null ;        
    while((line=br.readLine())!=null) { //通道内的流结束不是用null作为结束条件的
        /*if("over".equals(line)) {//让服务器读到这个结束条件
            break ;
        }*/
        bw.write(line);
        bw.newLine();
        bw.flush();
            
    }        
    //服务端获取通道内的输出流对象
    BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;
    //向客户端反馈
    bwServer.write("文件上传成功了");
    bwServer.newLine();
    bwServer.flush();
    //释放资源
    bw.close();
    s.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值