Java网络编程02

4.TCP网络通信编程

  • 基本介绍

    1. 基于客户端--服务端的网络通信
    2. 底层使用的是TCP/IP协议
    3. 应用场景举例:客户端发送数据,服务端接收并显示控制台
    4. 基于Scoket的TCP编程

4.1应用案例1:(使用字节流)

  1. 编写一个服务器端,和一个客户端
  2. 服务器端在9999端口监听
  3. 客户端连接到服务器端,发送“hello,server”,然后退出
  4. 服务器端接收到客户端发送的信息,输出,并结束

客户端思路:

1.连接服务端(ip,端口)

2.连接上后,生成socket,通过socket.getOutputStream()

3.通过输出流,写入数据到数据通道

package li.network.socket;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket; //发送"hello,server"给服务端
public class SocketTCP01Client {
public static void main(String[] args) throws IOException {
//1.连接服务端(ip,端口)
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
System.out.println("客户端 socket返回=" + socket.getClass()); //2.连接上后,生成socket,通过socket.getOutputStream()
// 得到和 socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream(); //3.通过输出流,写入数据到数据通道
outputStream.write("hello,server".getBytes()); //4. 关闭流对象和socket(必须关闭)
outputStream.close();
socket.close(); System.out.println("客户端退出");
}
}

服务器端思路:

1.在本机的9999端口监听,等待连接

2.当没有客户端连接9999端口时,程序将会阻塞,等待连接

3.通过socket.getInputStream()读取客户端写入到数据通道的数据,显示

package li.network.socket;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket; public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
// 1.在本机的9999端口监听,等待连接
// 要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接则会返回一个socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("服务器端 socket=" + socket.getClass()); // 3.通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
InputStream inputStream = socket.getInputStream(); // 4.IO读取
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));//根据实际读取到的长度显示内容
} // 5. 关闭流对象和socket(必须关闭)
inputStream.close();
socket.close();
serverSocket.close();//关闭serverSocket
}
}
  1. 要先运行服务端,这里显示正在等待连接客户端:

  1. 再运行客户端程序,得到一个socket,通过输出流将数据写入到数通道里面,然后退出:

  1. 服务器端会通过输入流不停地读取,把数据输出到控制台上,然后关闭退出:

4.2应用案例2:(使用字节流)

  1. 编写一个服务器端,和一个客户端
  2. 服务器端在9999端口监听
  3. 客户端连接到服务器端,发送“hello,server”,并接收服务器端回发的“hello,client”,再退出
  4. 服务器端接收到客户端发送的信息然后输出,并发送“hello,client”,再退出

注意设置写入结束标记socket.shutdownOutput(); 否则程序会认为还在写入数据。

服务端Server:

package li.network.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; @SuppressWarnings("all")
public class SocketTCP02Server {
public static void main(String[] args) throws IOException {
// 1.在本机的9999端口监听,等待连接
// 要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接则会返回一个socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("服务器端 socket=" + socket.getClass()); // 3.获取数据,通过socket.getInputStream()读取客户端写入数据通道的数据,并显示
InputStream inputStream = socket.getInputStream();
//IO读取
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));//根据实际读取到的字符串长度显示内容
} // 4. 回话,写入数据
// 获取socket相关的输出流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,client".getBytes());
//设置写入结束标记
socket.shutdownOutput(); // 5. 关闭流对象和socket(必须关闭)
inputStream.close();
outputStream.close();
socket.close();
serverSocket.close();//关闭serverSocket
}
}

客户端Client:

package li.network.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket; @SuppressWarnings("all")
//发送"hello,server"给服务端
public class SocketTCP02Client {
public static void main(String[] args) throws IOException {
//1.连接服务端(ip,端口)
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
System.out.println("客户端 socket返回=" + socket.getClass()); //2.连接上后,生成socket,通过socket.getOutputStream()
// 得到和 socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream(); //3.通过输出流,写入数据到数据通道
outputStream.write("hello,server".getBytes());
//设置写入结束标记
socket.shutdownOutput(); //4. 获取数据
// 获取和socket相关联的输入流,并显示
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));
} //5. 关闭流对象和socket(必须关闭)
outputStream.close();
inputStream.close();
socket.close(); System.out.println("客户端退出");
}
}
  1. 服务端等待客户端连接:

  1. 客户端往数据通道写入数据“hello,server,并接受到服务端发送的数据“hello,client”

  1. 服务端接收到数据:

4.3应用案例3:(使用字符流)

  1. 编写一个服务端,一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务端,发送“hello,server”,并接收到服务端会发的“hello,client”,然后退出
  4. 服务端接收到 客户端发送的信息,输出,并发送“hello,client”,再退出

思路答题与应用案例2一致,这里要求使用字符流,那么在拿到输入/输出字符流之后,使用转换流,将其转换为字符流即可。

PS:设置写入结束标记:除了使用socket.shutdownOutput(); 还可以使用writer.newLine(),如果使用这种结束标志的话,需要使用readLine()的方式读取

注意点:如果使用的是字符流,需要我们手动刷新xx.flush();,否则数据不会写入数据通道

服务端Server:

package li.network.socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket; //使用字符流
@SuppressWarnings("all")
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
// 1.在本机的9999端口监听,等待连接
// 要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接则会返回一个socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("服务器端 socket=" + socket.getClass()); // 3.获取数据,通过socket.getInputStream()读取客户端写入数据通道的数据,并显示
InputStream inputStream = socket.getInputStream();
//IO读取---使用字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);//输出 // 4. 回话,写入数据
// 获取socket相关的输出流
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello,client 字符流");
bufferedWriter.newLine();//插入一个换行符,表示回复内容的结束
bufferedWriter.flush();//手动刷新 // 5. 关闭流对象和socket(必须关闭)
bufferedWriter.close();//关闭外层流
bufferedReader.close();
socket.close();
serverSocket.close();//关闭serverSocket
}
}

客户端Client:

package li.network.socket;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket; @SuppressWarnings("all")
//发送"hello,server"给服务端,使用字符流
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
//1.连接服务端(ip,端口)
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
System.out.println("客户端 socket返回=" + socket.getClass()); //2.连接上后,生成socket,通过socket.getOutputStream()
// 得到和 socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream(); //3.通过输出流,写入数据到数据通道----使用字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello,server 字符流");
bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束,注意:要求对方使用readLine()!!!!
//如果使用的是字符流,需要我们手动刷新,否则数据不会写入数据通道
bufferedWriter.flush(); //4. 获取数据
// 获取和socket相关联的输入流,并显示
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s); //5. 关闭流对象和socket(必须关闭)
bufferedReader.close();//关闭外层流
bufferedWriter.close();
socket.close(); System.out.println("客户端退出");
}
}

4.4应用案例4:

  1. 编写一个服务端和一个客户端
  2. 服务器端在端口8888监听
  3. 客户端连接到服务端,并发送一张图片
  4. 服务器端接收到客户端发送的图片,保存到src目录下,然后发送“收到图片”,再退出
  5. 客户端接收到服务端的回话:“收到图片“ 之后,再退出
  6. 该程序要求使用StreamUtils.java

说明:使用BufferedInputStreasm和BufferedOutputStream字节流

思路如下:

  1. 客户端这边先将数据传输到客户端程序中,然后通过socket获取数据通道,将文件数据发送给服务端;

  2. 服务端这边,先是得到数据通道上的数据(传输到服务端程序中),然后使用将程序中的文件数据输出到某个目录下,之后在将“收到图片”的消息输出到数据通道上

  3. 客户端通过socket,从数据通道上获取回复消息,并打印在控制台上

工具类StreamUtils:

package li.network.upload;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; /**
* 此类用于演示关于流的读写方法
*
*/
public class StreamUtils {
/**
* 功能:将输入流转换成byte[],即可以把文件的内容写入到byte[]
* @param is
* @return
* @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];//字节数组
int len;
while((len=is.read(b))!=-1){//循环读取
bos.write(b, 0, len);//把读取到的数据写入到 bos流中
}
byte[] array = bos.toByteArray();//然后将bos 转成为一个字节数组
bos.close();
return array;
} /**
* 功能:将InputStream转换成String
* @param is
* @return
* @throws Exception
*/ public static String streamToString(InputStream is) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder= new StringBuilder();
String line;
while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
builder.append(line+"\r\n");
}
return builder.toString(); } }

服务端Server:

package li.network.upload;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket; //文件上传的服务端
public class TCPFileUploadServer {
public static void main(String[] args) throws Exception { // 1.服务端在监听8888端口(这里是在本机进行)
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端在8888端口监听...");
// 2.等待连接
Socket socket = serverSocket.accept(); //3.读取数据通道的数据
//通过socket获得输入流
//创建对象
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//写入到程序中
byte[] bytes = StreamUtils.streamToByteArray(bis);//streamToByteArray方法:将输入流转换成byte[] //4.将得到的bytes数组(文件数据)写入到指定的路径,就得到一个文件
String destFilePath = "src\\copy.png";
//创建对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
//写入数据到目录中
bos.write(bytes);
bos.close(); //5.收到图片后,向客户端回复“收到图片”
//通过socket获得输出流
//创建对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("收到图片");
bw.flush();//把内容刷新到数据通道
socket.shutdownOutput();//设置写入结束标记 //6.关闭其他资源
bw.close();
bis.close();
socket.close();
serverSocket.close();
}
}

客户端Client:

package li.network.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket; //文件上传的客户端
public class TCPFileUploadClient {
public static void main(String[] args) throws Exception {
//1.客户端连接服务端,得到一个socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 8888); //2.创建读取磁盘文件的输入流
String filePath = "d:\\ggmm.jpg";
//创建对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//这里的 bytes 就是 文件filePath 对应的字节数组
//读取数据到程序中
byte[] bytes = StreamUtils.streamToByteArray(bis); //3.通过socket获取输出流,将bytes数据发送到服务端
//创建对象
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//写入数据通道
bos.write(bytes);//将文件对应的字节数组写入到数据通道
bis.close();
socket.shutdownOutput();//设置写入数据的结束标志 //4.获取服务端回复的消息
InputStream inputStream = socket.getInputStream();
String s = StreamUtils.streamToString(inputStream);//streamToString方法:把一个输入流的数据直接转成字符串
System.out.println(s); //关闭相关的流
inputStream.close();
bos.close();
socket.close();
}
}

day40-网络编程02的更多相关文章

  1. Python网络编程02 /基于TCP、UDP协议的socket简单的通信、字符串转bytes类型

    Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes类型 目录 Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes ...

  2. day35 Pyhton 网络编程02

    一内容回顾 网络基础 网络应用开发架构 B/S架构   浏览器直接作为客户端的程序 C/S架构 B/S是特殊的C/S osi七层模型 应用层  python代码   http  https  ftp  ...

  3. Linux网络编程学习路线

    转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程   1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...

  4. 02网络编程( socket套接字+TCP粘包 )

    目录 02 网络编程 一.socket套接字编程 二.简易代码模板 2.1 服务端 2.2 客户端 三.通信循环及代码优化 四.黏包现象 五.struct模块 六.简易版本报头 七.上传文件数据 * ...

  5. Python Socket 网络编程

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  6. python网络编程-socket编程

     一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...

  7. 网络编程1--毕向东java基础教程视频学习笔记

    目录: 01 网络编程概述1 02 网络编程概述2 03网络编程 网络模型 04网络编程 IP地址 05网络编程 TCP和UDP 06网络编程 Socket 07网络编程 UDP发送端 01 网络编程 ...

  8. java网络编程socket解析

    转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...

  9. Linux C 程序 Linux网络编程(21)

    Linux网络编程网络编程必备的理论基础网络模型,地址,端口,TCP/IP协议 TCP/IP协议是目前世界上使用最广泛的网络通信协议日常中的大部分应用使用该系列协议(浏览网页,收发电子邮件,QQ聊天等 ...

随机推荐

  1. 机器学习-K近邻(KNN)算法详解

    一.KNN算法描述   KNN(K Near Neighbor):找到k个最近的邻居,即每个样本都可以用它最接近的这k个邻居中所占数量最多的类别来代表.KNN算法属于有监督学习方式的分类算法,所谓K近 ...

  2. 零基础学Java(3)运算符

    运算符 运算符用于连接值.Java提供了一组丰富的算术和逻辑运算符以及数学函数. 算术运算符 在Java中,使用算术运算符+.-.*./表示加.减.乘.除运算.当参与/运算的两个操作数都是整数时,表示 ...

  3. 最著名的著名的比特币BTC钱包地址-中本聪的钱包

    最著名的著名的比特币BTC钱包地址-中本聪的钱包1.比特币创始人中本聪 1PTFYUG6nCzRrByoRfGT5kefUNuZjNF84o这个地址还是比特币的创世地址,比特币从未移动过,其中的50币 ...

  4. 综合案例_文件搜索和FileFilter过滤器的原理和使用

    文件搜索 需求 : 遍历D:\aaa文件夹,及 aaa 文件夹的子文件夹并且只要.java结尾的文件 分析: 1.目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录 2.遍历目录时,获取的子文件 ...

  5. 使用Docker搭建自己的Bitwarden密码管理服务

    相信身为开发者,总会在各种网站中注册账号,为了方面记忆可以使用同一套账号密码进行注册,自从前段时间学习通时间撞库后有些人已经开始疯狂改密码了,可是密码一多就很难记忆,最好找个地方存储账户信息 我曾经使 ...

  6. ajax03_跨域访问问题

    ajax跨域访问问题 什么是跨域访问 从一个域名去访问另一个域名的资源 或者从一个站点去访问另一个站点的资源 哪些请求方式可以发送跨域请求 超链接 form表单 传统js代码 javascript标签 ...

  7. python 生成Windows快捷方式

    此处以虚拟机镜像快捷方式为例 link_filepath:快捷方式的生成路径 win32_cmd:需要执行的应用程序 arg_str:exe的参数 快捷方式的目标:由win32_cmd + arg_s ...

  8. 从matlab的bwmorph函数的'majority'参数中扩展的一种二值图像边缘光滑的实时算法。

    在matlab的图像处理工具箱中,有一系列关于Binary Images的处理函数,都是以字母bw开头的,其中以bwmorph函数选项最为丰富,一共有'bothat'.'branchpoints'.' ...

  9. tcp协议传输中的粘包问题

    什么是粘包问题 tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. ...

  10. linux文件校验

    最近在一次安装centos7程序中遇到了网速很卡的情况,不得已采用了百度云的离线下载功能,后来上传进入虚拟机内,结果遇到无法上传的情况,后来经过转码后才上传成功,详情http://www.cnblog ...