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

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

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

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没有关闭,那么读不到文件末尾,需要强制结束(判断文件长度是否一致)

相关推荐

开发者必看的八大Material Design开源项目

MaterialDesign是介于拟物和扁平之间的一种设计风格,自从它发布以来,便引起了很多开发者的关注,在这里小编介绍在Android开发者当中里最受青睐的八个MaterialDesign开源项...

另类插这么可爱,一定是…(另类t恤)

IT之家(www.ithome.com):另类插图:这么可爱,一定是…OSXMavericks和Yosemite打破了苹果对Mac操作系统传统的命名方式,使用加州的某些标志性景点来替换猫...

Android常用ADB命令(安卓adb工具是什么)

杀死应用①根据包名获取APP的PIDadbshellps|grep应用包名②执行kill命令...

微软Mac版PowerPoint测试Reading Order Pane功能

IT之家5月20日消息,微软公司昨日(5月19日)发布博文,邀请Microsoft365Insiders成员,测试macOS新版PowerPoint演示文稿应用,重点引入...

Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍

前言不同于iOS,Xamarin在VisualStudio中针对Android,可以直接设计使用者界面.在本篇教学文章中,笔者会针对Android的专案目录结构以及基本控制项进行介绍,包...

用云存储30分钟快速搭建APP,你信吗?

背景不管你承认与否,移动互联的时代已经到来,这是一个移动互联的时代,手机已经是当今世界上引领潮流的趋势,大型的全球化企业和中小企业都把APP程序开发纳入到他们的企业发展策略当中。但随着手机APP上传的...

谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果

Pine发自凹非寺量子位|公众号QbitAI当你拍照片时,“模特不好好配合”怎么办?...

iOS文本编辑控件UITextField和UITextVie

记录一个菜鸟的IOS学习之旅,如能帮助正在学习的你,亦枫不胜荣幸;如路过的大神如指教几句,亦枫感激涕淋!细心的朋友可能已经注意到了,IOS学习之旅系列教程在本篇公众号的文章中,封面已经换成美女图片了,...

Android入门图文教程集锦(android 入门教程)

Android入门视频教程集锦AndroidStudio错误gradientandroid:endXattributenotfound...

如何使用Android自定义复合视图(如何使用android自定义复合视图)

在最近的一个客户应用中,我遇到了一个需求,根据选定的值来生成指定数量的编辑框字段,这样用户可以输入人物信息。最初我的想法是把这些逻辑放到Fragment中,只是根据选中值的变化来向线性布局容器中增加编...

原生安卓开发app的框架frida常用关键代码定位

前言有时候可能会对APP进行字符串加密等操作,这样的话你的变量名等一些都被混淆了,看代码就可能无从下手...

教程10 | 三分钟搞定一个智能输入法程序

一案例描述1、考核知识点网格布局线性布局样式和主题Toast2、练习目标掌握网格布局的使用掌握Toast的使用掌握线性布局的使用...

(Android 8.1) 功能与新特性(android的功能)

和你一起终身学习,这里是程序员AndroidAndroid8.1(API级别27)为用户和开发人员引入了各种新特性和功能。本文档重点介绍了开发人员的新功能。通过本章阅读,您将获取到以下内容:Andr...

怎样设置EditText内部文字被锁定不可删除和修改

在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白了就是不可操作,只能在后面输入内容。在E...

如何阻止 Android 活动启动时 EditText 获得焦点

技术背景在Android开发中,当活动启动时,EditText有时会自动获得焦点并弹出虚拟键盘,这可能不是用户期望的行为。为了提升用户体验,我们需要阻止...