百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Java编程-TCP(Java编程软件)

wptr33 2024-11-16 01:28 65 浏览

1.1. Java的TCP

面向连接, 数据安全, 区分服务器端和客户端.

TCP分为Socket(客户端)和ServerSocket(服务端)

需要分别建立客户端和服务器端

客户端和服务端建立连接后,通过Socket中的IO流进行数据的传输

需要关闭关闭socket

同样,客户端与服务器端是两个独立的应用程序。

1.1.1. TCP客户端

第一步:创建客户端Socket

需要指定连接到服务器的地址和端口号, 并尝试连接

客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。

Socket socket = new Socket("192.168.1.220", 8888);

第二步:连接成功获取输入输出流

连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通getInputStream(),getOutputStream()获取即可。

socket.getInputStream();

socket.getOuputStream();

第三步: 将数据写出到服务端

使用字节输出流的write() 方法

第四步:关闭socket

调用close方法

连接成功之后获取输入输出流

socket.getInputStream();

socket.getOuputStream();

获取流之后就可以通过输入输出流发送和读取数据了, 客户端的输入流连接服务端输出流, 客户端输出流连接服务端输入流

客户端案例:

public class TcpClient {

public static void main(String[] args) throws IOException, IOException {

System.out.println("客户端启动...");

// 创建客户端

Socket socket = new Socket("127.0.0.1", 50000);

// 与服务端建立连接,获取输入输出流

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

// 将数据写出到服务端

System.out.println("客户端发送数据...");

out.write("Tcp,你好我是客户端...".getBytes());

// 关闭socket

out.close();

}

}


1.1.2. TCP服务端:

第一步: 创建服务端

ServerSocket, 需要指定端口号. 客户端连接的就是这个端口.

创建ServerSocket

ServerSocket serverSocket = new ServierSocket(8888);

第二步:和客户端建立连接

通过accept方法

Socket accept()

侦听并接受到此套接字的连接。

该方法会侦听是否有客户端连接,如果有建立连接,并获取客户端的Socket

也就是说服务端创建之后可以获取客户端连接, 返回一个Socket对象, 这个Socket就是和客户端连接的Socket

Socket socket = serverSocket.accept();

第三步: 接受客户端的数据,获取客户端的数据

服务端获取这个socket的输入输出流, 就可以和客户端发送接收数据了socket.getInputStream();

socket.getOutputStream();

第五步:获取客户端的ip地址和端口号

使用服务端获取的Socket 获取ip地址和端口.

InetAddress getInetAddress()

返回套接字连接的地址。


int getPort()

返回此套接字连接到的远程端口。

第四步:关闭客户端和服务端

在服务端中分别调用close方法.

1.1.3. 案例一:

客户端向服务端发送数据,服务端获取并进信息打印在控制台.

public class TcpServer {

public static void main(String[] args) throws IOException {

System.out.println("服务端启动:");

// 服务端,监听端口

ServerSocket server = new ServerSocket(50000);

// 使用acept进入侦听状态,获取客户端数据

Socket socket = server.accept();

// 获取输入流输出流

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

// 获取客户端ip,端口

InetAddress inetAddress = socket.getInetAddress();

String ip = inetAddress.getHostAddress();

int port = socket.getPort();

// 获取客户端数据

byte[] byt = new byte[1024];

System.out.println("服务端接受数据:");

int len = in.read(byt);

String mess = new String(byt, 0, len);

System.out.println("该客户端:" + ip + ":" + port + "发送了:" + mess);

// 关闭客户端

socket.close();

// 关闭服务端

server.close();

}

}

1.1.4. 案例二

客户端和服务端实现交互

客户端给服务端发送信息,并接收服务端的回馈信息。

例如:

首先客户端向服务器通话

客户端:你好吗?服务器

服务器接到信息

服务器:收到客户端消息

客户端说:你好吗?服务器

 服务器回馈信息

服务器:收到客户端消息

客户端说:你好吗?

服务器说:我很好

 客户端接到服务器的信息

客户端:你好吗?服务器

客户端: 收到服务器消息

服务器说: 我很好

客户端:

public class TcpClient {

public static void main(String[] args) throws IOException, IOException {

System.out.println("客户端启动...");

// 创建客户端

Socket socket = new Socket("127.0.0.1", 50000);

// 与服务端建立连接,获取输入输出流

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(

System.in));

byte[] byt = new byte[1024];

while (true) {

// 将数据写出到服务端

System.out.println("客户端发送数据...");


System.out.println("你说:");

String mess = br.readLine();

System.out.println("你告诉了服务端:");

out.write(mess.getBytes());

// 获取服务端的回话

int len = in.read(byt);

System.out.print("服务端告诉我了:");

System.out.println(new String(byt, 0, len));

if ("bye".equals(mess)) {

break;

}

}

// 关闭socket

out.close();

}

}

服务端:

public class TcpServer {

public static void main(String[] args) throws IOException {

System.out.println("服务端启动:");

// 服务端,监听端口

ServerSocket server = new ServerSocket(50000);

// 使用acept进入侦听状态,获取客户端数据

Socket socket = server.accept();

// 获取输入流输出流

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

// 获取客户端ip,端口

InetAddress inetAddress = socket.getInetAddress();

String ip = inetAddress.getHostAddress();

int port = socket.getPort();

byte[] byt = new byte[1024];

BufferedReader br = new BufferedReader(new InputStreamReader(

System.in));

while (true) {

// 获取客户端数据

System.out.println("服务端接收数据:");

int len = in.read(byt);

String mess = new String(byt, 0, len);

System.out.println("客户端:" + ip + ":" + port + "告诉了服务端:" + mess);

// 向客户端回话.

System.out.println("你要告诉客户端:");

String str = br.readLine();

out.write(str.getBytes());

if ("bye".equals(mess)) {

break;

}

}

// 关闭客户端

socket.close();

// 关闭服务端

server.close();

}

}


1.1.5. 案例三:

服务器可以客户端的连接.客户端通过键盘录入数据,发送到服务端,服务端接收到数据后,转换成大写在返回给客户端。

需求:

服务器可以客户端的连接.客户端通过键盘录入数据,发送到服务端,服务端接收到数据后,转换成大写在返回给客户端。

客户端:

public class Cilent {

public static void main(String[] args) throws UnknownHostException,

IOException {

System.out.println("客户端启动...");

Socket socket = new Socket("127.0.0.1", 50000);

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.println("请录入:");

String mess = br.readLine();

out.write(mess.getBytes());

System.out.println("-----------获取服务器的回馈--------------");

byte[] byt = new byte[1024];

int len = in.read(byt);

System.out.println(new String(byt, 0, len));

socket.close();

}

}

服务端:

public class Cilent {

public static void main(String[] args) throws UnknownHostException,

IOException {

System.out.println("客户端启动...");

Socket socket = new Socket("127.0.0.1", 50000);

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.println("请录入:");

String mess = br.readLine();

out.write(mess.getBytes());

System.out.println("-----------获取服务器的回馈--------------");

byte[] byt = new byte[1024];

int len = in.read(byt);

System.out.println(new String(byt, 0, len));

socket.close();

}

}

1.1.6. 多线程服务器

服务器一般是为多个客户端同时服务的, 当每个客户端连接到服务器时, 可以开一条单独的线程处理这个连接.

服务器端:

public class Server {

public static void main(String[] args) throws IOException {

System.out.println("服务器启动...");

ServerSocket server = new ServerSocket(50000);

while (true) {

Socket socket = server.accept();

ServerRunnable serverRunnable = new ServerRunnable(socket);

Thread t1 = new Thread(serverRunnable);

t1.start();

}

}

}

class ServerRunnable implements Runnable {

Socket socket;

ServerRunnable(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

byte[] byt = new byte[1024];

int len = in.read(byt);

String str = new String(byt, 0, len);

System.out.println(str);

System.out.println("------------服务器转大写--------------");

String upperCase = str.toUpperCase();

System.out.println(upperCase);

// 转大写,写回给客户端

out.write(upperCase.getBytes());

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}


1.1.7. 上传文件

分析:

先启动服务器,再启动客户端.客户端和服务端需要建立连接,服务端向客户端反馈信息.告知客户端”连接成功,请上传文件路径:

客户端:

一: 客户端需要检测文件是否存在,是否是文件.

二: 客户端将文件名,和文件的长度发给服务器,服务器以此判断文件是否存在,文件大小用以验证文件是否上传完毕.

三: 客户端根据服务器端的反馈信息,如果服务器存在该文件,上传结束,不存在开始上传.

四: 客户端开始上传, 使用字节输入流,将文件加载到输入流中,读取输入流,通过socket的输出流写到服务器.

五: 服务器:

根据客户传送的信息,判断文件是否存在如果存在不再上传,需要将结果反馈给客户端.

如果不存在,新建字节输出流,将客户端传送的数据,写到服务器中.判断服务器文件的长度和客户端文件的长度是否一致.一致上传完毕.

客户端:

public class Client {

public static void main(String[] args) throws IOException {

System.out.println("客户端启动");

Socket socket = new Socket("127.0.0.1", 5000);

InputStream ips = socket.getInputStream();

OutputStream ops = socket.getOutputStream();

// 1

ops.write("客户端请求上传文件".getBytes());

// 4

byte[] byt = new byte[1024];

int len = 0;

len = ips.read(byt);

String mess = new String(byt, 0, len);

System.out.println(mess);

// 获取上传文件

File file = getFile();

// 获取上传文件名

mess = file.getName();

System.out.println("文件名:" + mess);

// 5

ops.write(mess.getBytes());

// 7上传文件大小

ops.write(String.valueOf(file.length()).getBytes());

// 10

len = ips.read(byt);

mess = new String(byt, 0, len);

if ("文件存在".equals(mess)) {

System.out.println("文件存在,无需上传");

return;

}

// 11 上传

FileInputStream fis = new FileInputStream(file);

while ((len = fis.read(byt)) != -1) {

ops.write(byt, 0, len);

}

System.out.println("文件上传完毕");

len = ips.read(byt);

System.out.println("服务器说:" + new String(byt, 0, len));

ops.close();

socket.close();

}


private static File getFile() {

// 用户输入文件路径

Scanner sc = new Scanner(System.in);

while (true) {

System.out.println("请输入文件的路径名:");

String nextLine = sc.nextLine();

// 创建File

File file = new File(nextLine);

if (!file.exists()) {

System.out.println("文件不存在");

continue;

}

if (file.isDirectory()) {

System.out.println("不支持目录");

continue;

}

return file;

}

}

}

}

}

服务端:

public class Server {

public static void main(String[] args) throws IOException {

System.out.println("服务端启动");

ServerSocket server = new ServerSocket(5000);

Socket client = server.accept();

InputStream ips = client.getInputStream();

OutputStream ops = client.getOutputStream();

// 2

byte[] byt = new byte[1024];

int len = -1;

len = ips.read(byt);

System.out.println(new String(byt, 0, len));

// 3

ops.write("接收请求,请上传".getBytes());

// 5

len = ips.read(byt);

String fileName = new String(byt, 0, len);

System.out.println("文件名:" + fileName);

// 根据文件名创建File对象,

File file = new File("d:\\", fileName);

// 8获取文件长度

len = ips.read(byt);

long length = Long.parseLong(new String(byt, 0, len));

// 9判断文件是否存在

if (file.exists() && file.length() == length) {

System.out.println("文件已经存在");

ops.write("文件存在".getBytes());

return;

} else {

ops.write("文件不存在".getBytes());

}

// 12接收

FileOutputStream fos = new FileOutputStream(file);

while ((len = ips.read(byt)) != -1) {

fos.write(byt, 0, len);

fos.flush();

if (file.length() == length) {

System.out.println("文件上传完毕...");

ops.write("文件接收完毕".getBytes());

break;

}

}

fos.close();

client.close();

server.close();

}

}

注意: 服务器中的写出文件时,如果客户端socket没有关闭,那么读不到文件末尾,需要强制结束(判断文件长度是否一致)

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...