黑马程序员_Java基础_网络编程_TCP协议编程,客户端服务端程序

一,TCP通信

UPD通信分成发送端和接收端,而在TCP协议中则分成客户端和服务端。客户端对应的对象时Socket,服务端对应的对象时ServerSocket。客户端一建立就会去寻找服务端,原因正是因为TCP是面向连接的,所以Socket一建立服务必须要有服务端存在,并连接成功。形成通道后在该通道进行数据传输。

TCP/IP通信协议的特点在网络编程UDP中已经做过详细的概述)

 

1TCP通信客户端和服务端的基本建立方法:

需求:创建客户端和服务端,客户端连接上服务端后,向服务端发送一个数据。

 
(1)需求:定义客户端,发送数据到服务端.

步骤:

1,创建Socket服务,并指定要连接的主机和端口;

2,为了发送数据,应该获取Socket流中的输出流发送数据。


import java.io.*;
import java.net.*;
class TcpClient
{
    public static void main(String[] args) throws Exception {
        //创建Socket服务,指定主机和端口
        Socket s = new Socket("127.0.0.1",10060);
        //获取该Socket的输出流,传输数据
        OutputStream os = s.getOutputStream();
        os.write("嗨,你好。。。。".getBytes());
        
        //关闭客户端
        s.close();
    }
}

(2)需求:定义服务端接收数据并打印,在控制台上;

 

步骤:

    1,创建服务端的ServerSocket服务,并监听某个接口

    2,获取连接过来的客户端对象,通过accept方法,没有连接就会等待,知道有客户端链接过来,它是一个阻塞式方法;

    3,客户端发送过来数据,那么服务端使用对应的客户端对象,获取该对象的读取流读取数据并打印在控制台上。

    4,关闭服务端,可选项。


class TcpServer
{
    public static void main(String[] srgs) throws Exception{
        //创建Serversocket服务,监听10060端口
        ServerSocket ss = new ServerSocket(10060);
        //获取连接过来的客户端对象,用accept方法
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip);
        //获取该对象的读取流
        InputStream in = s.getInputStream();
        byte[] by = new byte[1024];
        int len = 0;
        len = in.read(by);
        String str = new String(by,0,len);
        System.out.println(str);
        s.close();//关闭客户端
    }
}

2,在上面的程序中只是客户端发送一个数据到服务端,服务单接受了,但是并没有给客户端一个反馈信息,如何能够在服务端接受客户端数据后给服务端一个反馈信息呢?

无论是客户端还是服务端,当得到Socket对象后,该对象就可以获取到Socket中的输入流和输出流,通过getInputStream()getOutputStream(),然后我们就可以通过流来进行客户端和服务端之间的数据传输了。

 

需求:创建客户端和服务端,当客户端连接上服务端后,向服务端发送一个数据,服务端接收到数据后给客户端一个反馈。


import java.io.*;
import java.net.*;
class TcpSend2
{
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("100.64.174.174",10050);
//获取Socket对象的输出流,给服务端发送数据
        OutputStream out = s.getOutputStream();
        out.write("客户端,你好。".getBytes());
//获取Socket对象的输入流,接受服务端发送过来的数据
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));
        s.close();
    }
}
class TcpServer2
{
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10050);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "....已连接");
//获取Socket对象的输入流,接受客户端发送过来的数据
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));
//获取Socket对象的输出流,发送数据给客户端
        OutputStream out = s.getOutputStream();
        Thread.sleep(6000);
        out.write("收到服务端数据。。。".getBytes());
        s.close();
        ss.close();
    }
}

3,客户端和服务端的交互

需求:实现客户端向服务端发送数据,服务端接收到数据后将数据转换成大写发送到客户端,客户端将数据打印到控制台;当客户端发送的数据是over时,结束服务;

 

分析:

客户端是在设备上操作数据,那么可以用到IO流的规律来思考问题

源:键盘录入操作的是:字符,用字符流客户端能获取的是Socket中的字字节流,要用到字节流转化成字符流要提高读取的效率,要用到缓冲区,所以:BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in))

目的:网络输出流

 

思路:

    1,建立Socket服务连接服务端

    2,获取键盘输入

    3,将数据发送给服务端

    4,等待服务端返回数据

    5,关闭服务端 


import java.io.*;
import java.net.*;
class TcpSend3
{
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("100.64.174.174",10080);
        //获取键盘录入
        BufferedReader bufr = 
            new BufferedReader(new InputStreamReader(System.in));
        //获取Socket中的输出流
    //  BufferedWriter bufOut = new 
            //BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        //可以采用目的输出流,即可以接收输入流,也可以接收输出流,并且可以自动换行和刷新
        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
        //获取Socket中的读取流,读取服务端返回的大写数据
        BufferedReader bufIn = new 
            BufferedReader(new InputStreamReader(s.getInputStream()));
        String line = null;
        while ((line = bufr.readLine())!=null)
        {
            if("over".equals(line))
                break;
            pw.println(line);
        //  bufOut.write(line);//此处只是将字符串写入到输出流中没有换行标志,
                    //服务端没看到回车键,所以服务端会以为数据没有写完,会一直等待
        //  bufOut.newLine();
        //  bufOut.flush();
            //读取服务端返回的大写数据
            String in = bufIn.readLine();//readLine方法只有在读取到结束标志即回车符时才会返回字符
            System.out.println("服务端返回的数据是: " + in );
        }
        bufr.close();
        s.close();
    }
}
class TcpServer3
{
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10080);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + ".....连接成功" + "\n");
        //获取Socket的输入流,接收数据,以转换成客户想要的结果
        BufferedReader bufIn = new 
            BufferedReader(new InputStreamReader(s.getInputStream()));
        //获取Socket的输出流,将数据转换后发送给客户
    //  BufferedWriter bufOut = new 
    //      BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
        String line = null;
        while ((line = bufIn.readLine())!=null)
        {
            System.out.println("客户端的数据是: " + line);
            pw.println(line.toUpperCase());
        //  bufOut.write(line.toUpperCase());
        //  bufOut.newLine();//如果不给出一个换行符,客户端接收数据时由于是单行读取,只有碰到回车符时才认为是
                    //读取结束,否则会处于一直等待;
        //  bufOut.flush();
        }
        s.close();
        ss.close();
    }
}

4 ,需求:创建客户端和服务端,通过 TCP 协议实现客户端享服务端上传文本文件。


import java.io.*;
import java.util.*;
import java.net.*;
class UpClient
{
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("127.0.0.1",10000);
        //客户端读取文件的源是硬盘,并且操作的是文本文件,读取字符串需要缓冲区
        BufferedReader bufr = new BufferedReader(new FileReader("server.txt"));
        
        //获取Socket服务流,为了便于打印和输出数据,将其包装成方便操作字符的流。
        InputStream in = s.getInputStream();
        Scanner scanner = new Scanner(in);
        OutputStream out = s.getOutputStream();
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(out),true);
        
        //循环读取硬盘的文件内容写入到输出流
        String line = "";
        while((line = bufr.readLine())!=null) {
            pw.println(line);
        }
        //关闭Socket输出流,给对方一个文本结束标记
        s.shutdownOutput();
        //获取服务端的反馈信息
        while(scanner.hasNextLine()) {
            System.out.println(scanner.nextLine());
        }
        in.close();
    }
}
class UpServer
{
    public static void main(String[] args) throws Exception {
        //创建服务器套接字,绑定到端口10000
        ServerSocket ss = new ServerSocket(10000);
        Socket s = ss.accept();
        //获取客户端IP地址
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "连接成功 ");
        InputStream in = s.getInputStream();
        OutputStream out = s.getOutputStream();
        
        //创建打印流,在指定目录创建一个文件
        PrintWriter pw = new PrintWriter(new FileWriter("C://server.java"),true);
        BufferedReader bufr = new BufferedReader(new InputStreamReader(in));
        
        //从输入流中读取内容,写入创建的文件
        String line = "";
        while((line = bufr.readLine())!=null) {
            pw.println(line);
        }
        pw.close();
        
        //给客户端一个反馈信息
        PrintWriter pw2 = new PrintWriter(new OutputStreamWriter(out));
        pw2.println("上传成功!");
        pw2.close();
    }
}

5 ,需求:创建客户端和服务端,使用 TCP 协议从客户端上传一张图片文件给服务端,服务端接收完毕后给客户端一个反馈信息。(原理和上传文本文件一样,只需要将上述示例的字符流换成字节流即可)


import java.io.*;
import java.net.*;
class PicClient
{
    public static void main(String[] args) throws Exception {
        //创建服务,连接到指定地址和端口
        Socket s = new Socket("100.64.174.174",10010);
        //创建文件输入流
        FileInputStream fi = new FileInputStream("1.jpg");
        
        //读取图片数据,写入到Socket的输出流
        OutputStream out =s.getOutputStream();
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = fi.read(buf))!=-1)
        {
            out.write(buf,0,len);
        }
        //关闭输出流,告诉服务端数据写入结束
        s.shutdownOutput();
        
        //获取服务端反馈信息
        InputStream in = s.getInputStream();
        byte[] b = new byte[1024];
        int num = in.read(b);
        System.out.println(new String(b,0,num));
        //关闭流
        fi.close();
        s.close();
    }
}
class PicServer
{
    public static  void main(String[] args) throws Exception {
        //建立服务端,绑定到本地10010端口
        ServerSocket ss = new ServerSocket(10010);
        Socket s = ss.accept();
        //获取链接成功的客户端IP地址
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "已连接");
        //获取Socket输入流,并且创建图片文件,将流中的数据写入到图片中
        InputStream in = s.getInputStream();
        FileOutputStream fo = new FileOutputStream("server.jpg");
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = in.read(buf))!=-1)
        {
            fo.write(buf,0,len);
        }
        
        //给客户端一个反馈信息
        OutputStream out = s.getOutputStream();
        out.write("上传成功".getBytes());
        out.flush();
        //关闭流
        fo.close();
        ss.close();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值