赞
踩
目录
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象
通信之前要保证连接已经建立(注意TCP是一定要建立连接的)
TCP是通过Socket产生I0流来进行网络通信的,所以发送端和接收端的两个流的方向是不一样的,比如客户端和服务器进行通信(通信前要确保建立了连接),然后客户端向服务器发送了“你好帅”,这一次发送数据的过程,它们流的方向是不一样的,针对客户端来说,它是往外发所以用的是输出流,而针对服务器来说,它是接收数据所以用的是输入流。
socket可以使一个应用从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接受字节流,当发送消息时,你需要知道对方的ip和端口,在java中,socket指的是java.net.Socket类。
一旦成功创建一个Socket类的实例,可以用它来发送和接收字节流,发送时调用getOutputStream方法获取一个java.io.OutputStream对象,接收远程对象发送来的信息可以调用getInputStream方法来返回一个java.io.InputStream对象。
Socket类代表一个客户端套接字,即任何时候连接到一个远程服务器应用时构建所需的socket。现在,要实现一个服务器应用,需要不同的做法。服务器需随时待命,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket,对应的是java.net.ServerSocket类。
ServerSocket与Socket不同,ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信。
(1)写TCP通信的步骤:
客户端:
创建客户端的Socket对象(Socket)与指定服务端连接:Socket(string host,int port)--host为服务器ip地址,port为端口
获取输出流,写数据:OutputStream getoutputstream()
释放资源:void close()
服务器:
创建服务器端的Socket对象(ServerSocket):Serversocket(int port)
监听客户端连接,返回一个Socket对象:Socket accept()
获取输入流,读数据,并把数据显示在控制台:InputStream getInputStream()
释放资源:void close()
示例:
提示:在客户端创建了Socket对象的同时会去连接服务端,如果连接不上,代码会报错;用来通信的I0流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了
客户端代码
- public class Client {
- public static void main(String[] args) throws IOException {
- //TCP协议,发送数据
- // 1.创建Socket对象
- // 提示:在创建对象的同时会连接服务端,如果连接不上,代码会报错
- Socket socket = new Socket("127.0.0.1",10001);
- //2.可以从连接通道中获取输出流(OutputStream是引用型数据类型)
- OutputStream os = socket.getOutputStream();
- //写出数据
- //os.write("aaa".getBytes());
- os.write("你好aaa是吧".getBytes());
- //3.释放资源
- os.close();//这里的流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了
- socket.close();
- }
- }

服务器代码
- public class Server {
- public static void main(String[] args) throws IOException {
- //TCP协议,接收数据
- // 1.创建对象ServerSocket
- ServerSocket ss = new ServerSocket(10001);
- //2.监听客户端的链接
- Socket socket = ss.accept();
- //3.从连接通道中获取输入流读取数据
- InputStreamReader br = new InputStreamReader(socket.getInputStream());//这时候才能正确的读取到中文数据
- int b;
- while ((b = br.read()) != -1) {
- System.out.print((char) b);
- }
- //4.释放资源
- br.close();//这里的流可以关可不关,因为这个流是TCP连接通道里的流,关闭TCP连接通道时这个流自然就关了
- ss.close();
- }
- }

先运行服务器,再运行客户端
结果结果
(2)客户端不断发送消息
客户端代码
- public class Client {
- public static void main(String[] args) throws IOException {
- //客户端:多次发送数据
- //服务器:接收多次接收数据,并打印
- //1.创建Socket对象
- Socket socket = new Socket("127.0.0.1",10001);
- //2.可以从连接通道中获取输出流(OutputStream是引用型数据类型)
- OutputStream os = socket.getOutputStream();
- Scanner sc = new Scanner(System.in);
- while (true) {
- System.out.println("输入要发送的数据:");
- String str = sc.nextLine();
- if ("886".equals(str)) {
- break;
- }
- //写出数据
- os.write(str.getBytes());
- }
- //3.释放资源
- socket.close();
- }
- }

服务器代码
- public class Server {
- public static void main(String[] args) throws IOException {
- //客户端:多次发送数据
- //服务器:接收多次接收数据,并打印
- // 1.创建对象ServerSocket
- ServerSocket ss = new ServerSocket(10001);
- //2.监听客户端的链接
- Socket socket = ss.accept();
- //3.从连接通道中获取输入流读取数据
- InputStreamReader br = new InputStreamReader(socket.getInputStream());
- int b;
- while ((b = br.read()) != -1) {
- System.out.print((char) b);
- }
- //4.释放资源
- ss.close();
- }
- }

运行结果:客户端发送886后结束通信
(3)客户端和服务器互发互收消息
- //客户端代码
- public class Client {
- public static void main(String[] args) throws IOException {
- Socket socket = new Socket("127.0.0.1",10001);
- OutputStream os = socket.getOutputStream();
- String str = "你看的到我发信息吗?";
- os.write(str.getBytes());
- //往服务器写出结束标记,shutdownOutput()是关闭输出流,如果不关闭,服务器那边的输入流就不会关闭,就会继续阻塞在读信息的过程中
- socket.shutdownOutput();
-
- InputStreamReader br = new InputStreamReader(socket.getInputStream());
- int b;
- while ((b = br.read()) != -1) {
- System.out.print((char) b);
- }
- socket.close();
- }
- }
-
-
-
- //服务器代码
- public class Server {
- public static void main(String[] args) throws IOException {
- ServerSocket ss = new ServerSocket(10001);
- Socket socket = ss.accept();
- InputStreamReader br = new InputStreamReader(socket.getInputStream());
- int b;
- while ((b = br.read()) != -1) {
- System.out.print((char) b);
- }
- socket.getOutputStream().write("是的,我看到了。".getBytes());//链式编程
- //写出结束标记,shutdownOutput()是关闭输出流
- socket.shutdownOutput();
- socket.close();
- ss.close();
- }
- }

运行结果
服务器端:
客户端:
Java网络编程中的UDP(User Datagram Protocol)通信编程支持单播、组播和广播这三种方式。
- 单播(Unicast):单播是指将数据从一个发送者发送到一个接收者的传输方式。在UDP编程中,通过指定目标主机的IP地址和端口号,可以实现单播通信。
- 组播(Multicast):组播是指将数据从一个发送者发送到一组特定的接收者的传输方式。在UDP编程中,可以使用Java的MulticastSocket类来支持组播通信。
- 广播(Broadcast):广播是指将数据从一个发送者发送到网络中的所有设备的传输方式。在UDP编程中,可以通过指定广播地址(通常是特定的子网地址)来实现广播通信。
单播:前面的发送接收数据的通信方式就是单播
组播:组播地址:224.0.0.0~239.255.255.255;其中224.0.0.0~224.0.0.255为预留的组播地址
广播:广播地址:255.255.255.255
UDP组播示例:
- //发送端代码
- public class SendMessageDemo {
- public static void main(String[] args) throws IOException {
- //组播发送端代码
- // 创建MulticastSocket对象
- MulticastSocket ms = new MulticastSocket();
- String str = "你好,你好!";
- byte[] bytes = str.getBytes();
- InetAddress address = InetAddress.getByName("224.0.0.2");//这里设置的ip为组播地址
- int port = 10000;
- DatagramPacket dp = new DatagramPacket(bytes, bytes.length,address,port);
- //调用MulticastSocket发送数据方法发送数据
- ms.send(dp);
- //释放资源
- ms.close();
- }
- }
-
-
-
- //接收端代码
- public class ReceiveMessageDemo1 {
- public static void main(String[] args) throws IOException {
- //1.创建MulticastSocket对象,并且设置端口为10000
- MulticastSocket ms = new MulticastSocket(10000);
- //2.将将当前本机,添加到224.0.0.1的这一组当中
- InetAddress address = InetAddress.getByName("224.0.0.2");
- ms.joinGroup(address);
-
- byte[] bytes = new byte[1024];
- DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
- //接收数据包
- ms.receive(dp);
- //3.解析数据包
- byte[] data = dp.getData();//获取数据包dp中的数据
- int len = dp.getLength();//获取这次收到了多少个字节的数据
- String str = new String(data,0,len);
- //因为字节数组data的长度是1024,太大了,所以要用到这次收到了多少个字节的数据个数len来决定把字节数组data中的多少数据转换成字符串
- String ip = dp.getAddress().getHostAddress();//ip
- String name = dp.getAddress().getHostName();//主机名
-
- System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + str);
- //释放资源
- ms.close();
- }
- }

要想运行并验证这个示例,修要允许运行多个发送端,步骤如下:
完成这些操作后,多运行几个接收端就可以了
发送端运行结果
接收端1显示结果
接收端2显示结果
UDP广播示例:
发送端把目的主机的IP设置为:255.255.255.255,这就是广播了
- public class SendMessageDemo {
- public static void main(String[] args) throws IOException {
- /*
- 按照下面的要求实现程序
- UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
- UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
- */
- //1.创建对象DatagramSocket的对象
- DatagramSocket ds = new DatagramSocket();
- Scanner sc = new Scanner(System.in);
- while (true) {
- System.out.println("请输入你想说的话:");
- String str = sc.next();
- byte[] bytes = str.getBytes();
- //InetAddress address = InetAddress.getByName("127.0.0.1");//设置目标主机的IP为:127.0.0.1,这是单播方式
- InetAddress address = InetAddress.getByName("255.255.255.255");//设置目标主机的IP为:255.255.255.255,这是广播方式
- int port = 10086;//设发送到目标主机的10086端口
- //2.打包数据
- DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
- //3.发送数据
- ds.send(dp);
- if ("886".equals(str)) {//如果输入的数据是886,发送数据结束
- break;
- }
- }
- //4.释放资源
- ds.close();
- }
- }

推荐:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。