Java编程-TCP JAVA编程手机软件

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

相关文章

3000字讲讲TCP协议,握手挥手不是你想的那么简单

专注于Java领域优质技术,欢迎关注作者: tobe 来自:tobe的呓语上一次讲了 UDP 协议,从这次开始,就要讲 TCP 协议了,因为 TCP 协议涉及到的东西很多,一篇文章概括不完,所以我把...

Java网络编程---TCP通信 java的tcp通讯协议数据传输

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信Java对基于TCP协议的网...

用 Wireshark 让你看见 TCP 到底是什么样

前言当你看到这篇文章时,你只能看到已经渲染好的文字和图像,而网络数据的交互对我们来说,却是看不见的,所以学习计算机网络原理的时候就会觉得非常的抽象,这一度让我苦恼。而且网络数据交换真实的模样,到底是不...

一文带你搞定TCP流量控制 tcp流量控制算法

摘要理想的流量控制实际的流量控制窗口关闭糊涂窗口综合征理想的流量控制什么是流量控制?流量控制就是发送方不能无脑的给接收方发送数据,它需要根据接收方的处理能力来发送数据。理想下的流量控制?理想意味着在实...

有关TCP协议,这是我看过讲的最清楚的一篇文章了!

TCP 协议是网络传输中至关重要的一个协议,它位于传输层。向上支持 FTP、TELNET、SMTP、DNS、HTTP等常见的应用层协议,向下要与网络层的 IP 协议相互配合,实现可靠的网络传输。分层网...