主页 > IT业界  > 

【Java】TCP网络编程(字节/符流)

【Java】TCP网络编程(字节/符流)

文章目录 概念TCP网络编程ServerSocketsocket使用区别和原理演示

概念

TCP(传输控制协议)是一种面向连接的协议,用于在计算机网络中可靠地传输数据。TCP是Internet协议族中的一个核心协议,它在传输层提供可靠、有序、基于流的传输服务。

网络编程是使用计算机网络进行编程的过程,可以使用各种编程语言和协议来实现网络通信。TCP网络编程是指使用TCP协议进行网络通信的编程技术。

TCP网络编程

TCP网络编程有两种模式,一种是服务器模式,另一种是客户端模式。服务器模式创建一个服务程序,等待客户端用户的连接,接收到用户的连接请求后,根据用户的请求进行处理;客户端模式则根据目的服务器的地址和端口进行连接,向服务器发送请求并对服务器的响应进行数据处理。

ServerSocket类和socket类(服务端/客户端)实现了基于TCP协议网络程序


客户端程序发起连接,形成数据通道,发给信息给服务端;服务器端在某个端口进行监听(这里以9999端口作为演示),当客户端连接到服务端后,实际上客户端是通过一个端口和服务端进行通讯的,这个端口是TCP/IP分配的(服务端通信的端口是固定的)

服务端 1.在本机的9999端口监听,等待连接 2.当没有客户端连接9999端口时,程序会阻塞,等待连接 3.通过socket.getInputStream()方法来读取客户端写入到通道的数据 客户端 1.连接服务端(IP,端口) 2.连接上后,会生成Socket,通过socket.getOutputStream() 3.通过输出流,写入数据到数据通道

ServerSocket

在客户/服务器通信模式中,服务器端需要创建监听特定端口的ServerSocket,ServerSocket负责接收客户连接请求。(用于监听端口)

该类提供了四个构造器,根据不同的场景进行选择 常用方法

accept():侦听并接受此套接字的连接;当有客户端连接的时候会返回一个Socket对象。此方法在连接传入之前一直阻塞

此代码执行之后,只会输出服务端在9999端口监听等待连接,而后一直阻塞等待(只有返回socket对象之后才会继续)

import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class SocketTCP01Server { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听等待连接"); Socket socket = serverSocket.accept(); System.out.println("服务器端:"+socket.getClass()); } catch (IOException e) { e.printStackTrace(); } } }

注意:要求被监听的端口没有被其他服务或程序占用,否则会出异常

socket

这个类实现了客户端套接字(也被称为“套接字”)。套接字是两台机器之间的通信的一个端点。 用于客户端与服务端之间的连接,如果连接成功返回Socket对象

该类提供了9个构造器,根据不同的场景进行选择 这里使用常用的Socket(InetAddress address, int port) 作为演示

address:IP地址port:端口号

常用方法

getInputStream():返回socket的输入流,用于接收数据getOutputStream:返回socket的输出流,用于发送数据shutdownOutput():表示一个Output结束标记,表示后面没有要输入的东西shutdownInput():表示一个Input结束标记,表示后面没有要读的数据了

通常Socket构造器中的IP地址写的是远程服务器的IP地址,这里作为演示使用本机IP

InetAddress.getLocalHost();//获取本机IP

此时先执行ServerSocket中监听指定端口(代码在ServerSocket中),然后执行下列代码,会连接成功

import java.io.IOException; import java.net.InetAddress; import java.net.Socket; public class SocketTCP01Client { public static void main(String[] args) { try { //连接本机的9999端口 Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端:连接成功"+socket.getClass()); } catch (IOException e) { e.printStackTrace(); } } }

客户端和服务端各有一个Socket对象

使用区别和原理演示

区别 当serverSocket.accept()时,可以返回多个socket对象(多并发)一台计算机可以同时提供多个服务,这些不同的服务之间通过端口号来区别,不同的端口号上提供不同的服务。当多个服务(服务器)连接同一个端口时,accept之后会返回多个socket对象

工作原理

服务端:监听端口,等待连接客户端:连接服务端端口,返回Socket对象,同时服务端也返回Socket对象客户端:连接上后,通过socket.getOutputStream()得到socket对象关联的输出流对象客户端:通过输出流,写入数据服务端:通过socket.getInputStream()读取客户端写入到数据通道的数据,并输出客户端和服务端:socket和流进行关闭(close),避免造成资源浪费

代码演示 理论上服务端和客户端的程序应该是在不同的机器上的,这里为了方便,使用了一台机器(可以自行设置虚拟机)

1.客户端连接到服务端,发送hello server并退出;服务端接收到客户端的信息,打印并退出

以下代码执行过后,服务端会输出客户端发来的信息,先执行服务端,在执行客户端。如果出现异常,可以把电脑防火墙关闭

这里使用的String类中getBytes方法(字符串转字节数组)和String的构造器

服务端

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) { InputStream inputStream = null; Socket socket = null; try { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听等待连接"); socket = serverSocket.accept(); inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int len =0; while ((len=inputStream.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); } } catch (IOException e) { e.printStackTrace(); }finally { try { socket.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }

客户端

import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class SocketTCP01Client { public static void main(String[] args) { Socket socket = null; OutputStream outputStream = null; try { socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端:连接成功"+socket.getClass()); outputStream = socket.getOutputStream(); outputStream.write("hello,server".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { try { socket.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }

2.客户端连接到服务端,发送hello,server,并接收服务端回发的hello,client并退出;服务端接收到客户端的信息,输出并退出

注意:在发送完一个数据的时候,需要有一个结束标记,表示该数据发送完毕,可以发送下一个,要不然当多个数据发送时,会出现死锁的情况。

服务端

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class SocketTCP02Server { public static void main(String[] args) { ServerSocket serverSocket = null; InputStream inputStream = null; Socket socket = null; OutputStream outputStream = null; try { serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听等待连接"); socket = serverSocket.accept(); inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int len = 0; System.out.println("客户端发的信息为:"); while ((len = inputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, len)); } socket.shutdownInput();//表示一个结束标记 outputStream = socket.getOutputStream(); outputStream.write("hello,client".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); inputStream.close(); outputStream.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }

客户端

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class SocketTCP02Client { public static void main(String[] args) { Socket socket = null; OutputStream outputStream = null; InputStream inputStream = null; try { socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端:连接成功"+socket.getClass()); outputStream = socket.getOutputStream(); outputStream.write("hello,server".getBytes()); socket.shutdownOutput();//表示一个结束标记 inputStream = socket.getInputStream(); byte[] buf = new byte[1024]; int readlen = 0; System.out.println("服务端发的信息为:"); while ((readlen = inputStream.read(buf))!=-1){ System.out.println(new String(buf,0,readlen)); } } catch (IOException e) { e.printStackTrace(); }finally { try { socket.close(); outputStream.close(); inputStream.close(); System.out.println("客户端退出"); } catch (IOException e) { e.printStackTrace(); } } } }

3.使用TCP字符流完成网络数据通讯演示(这里使用了转换流,把字节流转换为字符流),如果使用字符流需要手动刷新,调用flush方法,否则数据不会写入

注意:newLine()也可以是设置写入标记(换行符),需要对方使用readLine():读取结束标记才可以

服务端

import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class SocketTCP03Server { public static void main(String[] args) { ServerSocket serverSocket = null; InputStream inputStream = null; Socket socket = null; OutputStream outputStream = null; BufferedWriter bufferedWriter = null; try { serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听等待连接"); socket = serverSocket.accept(); inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println(bufferedReader.readLine()); // socket.shutdownInput();//表示一个结束标记 outputStream = socket.getOutputStream(); bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,client字符流"); bufferedWriter.newLine();//结束标记 bufferedWriter.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); serverSocket.close(); bufferedWriter.close();//关闭外层流即可 } catch (IOException e) { e.printStackTrace(); } } } }

客户端

import java.io.*; import java.net.InetAddress; import java.net.Socket; public class SocketTCP03Client { public static void main(String[] args) { Socket socket = null; OutputStream outputStream = null; InputStream inputStream= null; BufferedReader bufferedReader = null; try { socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端:连接成功"+socket.getClass()); outputStream = socket.getOutputStream(); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,server字符流"); bufferedWriter.newLine();//换行符,在这里表示结束标记 bufferedWriter.flush(); // socket.shutdownOutput();//表示一个结束标记 inputStream = socket.getInputStream(); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println(bufferedReader.readLine()); } catch (IOException e) { e.printStackTrace(); }finally { try { socket.close(); bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
标签:

【Java】TCP网络编程(字节/符流)由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【Java】TCP网络编程(字节/符流)