黑马程序员-网络编程(二)

——- android培训java培训、期待与您交流! ———-

1.1 TCP

1.1.1 文字发送 Demo

服务端:

package com.test.blog5;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ServerDemo {

    public static void main(String[] args) throws IOException {
        // 创建服务端对象
        ServerSocket ss = new ServerSocket(10002);
        // 获取连接过来的客户端对象。
        Socket s = ss.accept();// 阻塞式
        // String ip = s.getInetAddress().getHostAddress();
        // 通过 socket 对象获取输入流,要读取客户端发来的数据。
        InputStream in = s.getInputStream();

        byte[] buf = new byte[24];

        // int len = in.read(buf);
        int len = 0;
        // String text = new String(buf,0,len);
        // System.out.println(ip + ":" + text);
        StringBuilder sb = new StringBuilder();
        while ((len = in.read(buf)) != -1) {
            // sb.append(new String(buf, 0, len));
            System.out.println("服务端接收到数据:" + new String(buf, 0, len));
        }
        s.close();
        ss.close();
    }
}

客户端:

package com.test.blog5;

import java.net.Socket;
import java.io.OutputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.InputStream;

public class ClientDemo {
    public static void main(String[] args) throws UnknownHostException,
            IOException {
        // 创建客户端socket服务。
        Socket socket = new Socket("127.0.0.1", 10002);
        // 获取socket流中的输出流
        OutputStream out = socket.getOutputStream();
        // 使用输出流将指定的数据写出去。
        out.write("TCP客户端发送数据".getBytes());

        // 断开链接,关闭资源,socket获取的输出流也被关闭,没有必要再写代码关闭
        socket.close();
    }
}

启动服务端,然后启动客户端,运行结果:

这里写图片描述

1.1.2 交互Demo

发送端发送数据,服务端收到后返回数据

服务端:

package com.test.blog5;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ServerDemo {

    public static void main(String[] args) throws IOException {
        // 创建服务端对象
        ServerSocket ss = new ServerSocket(10002);
        // 获取连接过来的客户端对象。
        Socket s = ss.accept();// 阻塞式
        // String ip = s.getInetAddress().getHostAddress();
        // 通过 socket 对象获取输入流,要读取客户端发来的数据。
        InputStream in = s.getInputStream();

        byte[] buf = new byte[24];

        // int len = in.read(buf);
        int len = 0;
        // String text = new String(buf,0,len);
        // System.out.println(ip + ":" + text);
        // StringBuilder sb = new StringBuilder();
        while ((len = in.read(buf)) != -1) {
            // sb.append(new String(buf, 0, len));
            System.out.println("服务端接收到数据:" + new String(buf, 0, len));
        }
        // 使用客户端socket对象的输出流给客户端返回数据
        OutputStream out = s.getOutputStream();
        out.write("收到".getBytes());
        s.close();
        ss.close();
    }
}

客户端:

package com.test.blog5;

import java.net.Socket;
import java.io.OutputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.InputStream;

public class ClientDemo {
    public static void main(String[] args) throws UnknownHostException,
            IOException {
        // 创建客户端socket服务。
        Socket socket = new Socket("127.0.0.1", 10002);
        // 获取socket流中的输出流
        OutputStream out = socket.getOutputStream();
        // 使用输出流将指定的数据写出去。
        out.write("TCP客户端发送数据".getBytes());
        socket.shutdownOutput();// 重要,告诉服务端发送完毕
        // 读取客户端返回的数据,使用Socket读取流。
        InputStream in = socket.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        String text = new String(buf, 0, len);

        System.out.println(text);

        // 断开链接,关闭资源,socket获取的输出流也被关闭,没有必要再写代码关闭
        socket.close();
    }
}

运行结果:
这里写图片描述

这里写图片描述

1.1.3 上传图片到服务器

服务端:

package com.test.blog5;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class PicUploadServer {
    private static String pic = "d:" + File.separator + "pics";
    private static String picType = ".jpg";

    /*
     * TCP--图片上传服务端
     */
    public static void main(String[] args) {
        try {
            System.out.println("图片服务端启动成功-----------");
            ServerSocket ss = new ServerSocket(10006);
            Socket s = ss.accept();
            // 接收图片的目录路径
            File dir = new File(pic);
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 定义接收客户端发送数据的流,注意是图片,不是文本数据,所以不用write类的包装
            InputStream is = s.getInputStream();
            // 定义往服务端存储文件的流
            FileOutputStream fos = new FileOutputStream(new File(dir,
                    System.currentTimeMillis() + picType));

            // 定义读取数据缓冲区
            byte[] buf = new byte[1024];
            int len = 0;
            // 将数据写入
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            // 给客户端返回信息
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(
                    s.getOutputStream()), true);

            pw.println("上传图片成功");

            is.close();
            fos.close();
            s.close();
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端

package com.test.blog5;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class PicUploadClient {
    /*
     * TCP--图片上传客户端
     */
    public static void main(String[] args) {
        try {
            System.out.println("图片客户端启动成功-----------");
            Socket s = new Socket("127.0.0.1", 10006);
            OutputStream os = s.getOutputStream();

            File file = new File("d:\\3.jpg");
            if (!file.exists()) {
                throw new FileNotFoundException("文件不存在");
            }
            // 定义原始数据流
            FileInputStream fis = new FileInputStream(file);
            // 定义数据缓冲区
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = fis.read(buf)) != -1) {
                os.write(buf, 0, len);
            }
            s.shutdownOutput();// 重要,告诉服务端发送完毕,否则会出现死等现象
            // 拿到客户端的读入流
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            // 读取服务端返回信息
            String result = br.readLine();
            System.out.println("结果:" + result);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

运行结果:

这里写图片描述

这里写图片描述

1.1.4 上传文本到服务器

服务端:

package com.test.blog5;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {
    /*
     * 上传文本文件服务端
     */
    public static void main(String[] args) {
        ServerSocket ss;
        try {
            System.out.println("服务端启动成功-----------");
            ss = new ServerSocket(10005);
            Socket s = ss.accept();
            System.out.println(s.getInetAddress().getHostAddress() + "链接成功");
            // 定义读取客户端发送数据的流
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            // 定义往服务端存数据的流
            PrintWriter pw = new PrintWriter(new FileOutputStream(
                    "d:\\upload.txt"), true);
            // 定义给客户端返回信息的流
            PrintWriter out = new PrintWriter(s.getOutputStream(), true);

            // 开始接收客户端信息并写入到服务端文件
            String line = "";
            while ((line = br.readLine()) != null) {
                System.out.println(line);
                pw.write(line + "\r\n");
                pw.flush();
            }
            // 保存完毕给客户端返回信息
            out.println("上传成功!");
            br.close();
            pw.close();
            out.close();
            s.close();
            ss.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

客户端:

package com.test.blog5;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class UploadClient {

    /*
     * 上传文本文件客户端
     */
    public static void main(String[] args) {

        try {
            System.out.println("客户端启动成功-----------");
            Socket s = new Socket("127.0.0.1", 10005);
            // 定义读取源文件的流
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    new FileInputStream("d:\\out.txt")));
            // 定义向服务端发送数据的流
            PrintWriter out = new PrintWriter(new OutputStreamWriter(
                    s.getOutputStream()), true);
            // 定义读取服务端返回信息的流
            BufferedReader brin = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));

            String line = "";
            while ((line = br.readLine()) != null) {
                out.println(line);
            }
            //告诉服务端,客户端写完了,此步骤非常重要,不然服务端会阻塞一直在等待
            s.shutdownOutput();
            // 输出服务端返回的信息
            System.out.println("服务端返回:" + brin.readLine());
            br.close();
            out.close();
            s.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果:
这里写图片描述

1.2 总结

****TCP传输流程:
**客户端:
建立Socket服务,并制定要连接的主机和端口;
获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
获取Socket流中的输出流InputStream,获取服务端的反馈信息;
关闭资源。
**服务端:
建立ServerSocket服务,并监听一个端口;
通过ServerSocket服务的accept方法,获取Socket服务对象;
使用客户端对象的读取流获取客户端发送过来的数据;
通过客户端对象的写入流反馈信息给客户端;
关闭资源;

1.3 注意

  • Tcp连接方式必须先启动服务端后启动发送端
  • 客户端告诉服务端发送完毕,避免双方阻塞死等现象。可以使用约定的结束符来判定,但是不是最好的方法,推荐使用socket.shutdownOutput();
  • 同时处理多个客户端使用多线程
  • 对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭。所以一般不用关闭流,直接关闭socket就可以了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员是一家IT培训机构,提供各种技术培训课程,包括网络通信相关的课程。在网络通信中,socket是一种编程接口,用于实现不同主机之间的通信。通过socket函数创建一个套接字,指定域名、类型和协议。域名可以是AF_INET、AF_INET6或AF_UNIX,类型可以是SOCK_STREAM(用于TCP通信)或SOCK_DGRAM(用于UDP通信),协议可以是0表示自动选择适合的协议。创建成功后,套接字会返回一个文件描述符,用于在后续的通信中进行读写操作。 在TCP通信中,服务器和客户端的流程大致相同。服务器首先使用socket函数创建套接字,然后使用bind函数绑定服务器地址结构,接着使用listen函数设置监听上限。服务器通过accept函数阻塞监听客户端连接,并使用read函数读取客户端传来的数据,进行相应的处理后,使用write函数将处理后的数据写回给客户端,最后使用close函数关闭套接字。客户端也是先使用socket函数创建套接字,然后使用connect函数与服务器建立连接,之后使用write函数将数据写入套接字,再使用read函数读取服务器返回的数据,最后使用close函数关闭套接字。 在UDP通信中,服务器和客户端的流程也有所不同。服务器使用socket函数创建套接字,指定类型为SOCK_DGRAM,然后使用bind函数绑定服务器地址结构。服务器通过recvfrom函数接收客户端传来的数据,并进行相应的处理,最后使用sendto函数将处理后的数据发送回给客户端。客户端同样使用socket函数创建套接字,然后通过sendto函数将数据发送给服务器,再使用recvfrom函数接收服务器返回的数据。 总之,socket网络通信是通过创建套接字实现不同主机之间的通信。根据使用的协议不同,可以选择TCP或UDP通信方式。服务器和客户端根据流程进行相应的操作,实现数据的传输和交互。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值