JAVA——基于TCP协议的文本聊天程序

版权声明:DY https://blog.csdn.net/Atishoo_13/article/details/82872894

基于TCP协议的文本聊天程序


1.要求

使用JAVA完成一个基于TCP协议的文本聊天程序,建立TCP客户端套接字,分别为服务端和客户端,并使两端可以互联。

2.TCP协议

在TCP协议中,有服务器端(Server端)和客户端(Client端)的概念。TCP传输数据的过程是:服务器端程序在本机的某个端口上监听,等待客户端连接到此端口,一旦客户端连接到了此端口,服务器端和客户端就可以进行数据传输了,数据传输结束后,关闭连接。下图为TCP数据传输过程。
在这里插入图片描述

3.语法

在JAVA类库中,与Socket相关的类都在java.net这个包中。InetAddress是代表IP地址的类,ServerSocket就是代表服务器端的类,Socket是代表客户端的类,同时也可以看作是代表连接的类,以下将对这三个类做一个简单的介绍:

  • InetAddress类
    InetAddress类的构造方法是私有的,所以我们不能够通过new关键字来创建一个InetAddress类的实例。但是InetAddress类有几个静态方法,可以用于生成InetAddress的实例。我们在此处用到的就是getByAddress(byte[])这个静态的方法。这个方法的参数是一个byte数组。我们知道,一个IP地址是由4个字节组成的,只要将这4个字节顺序放在一个byte数组中,然后将它作为参数传递给这个方法,就可以得到一个IP地址。
  • ServerSocket类
    ServerSocket类代表了服务器端,根据图19-5,它有以下几个方法。
    1)构造方法ServerSocket(int):参数是一个端口号,ServerSocket的实例创建出来后,会在指定的端口监听。
    2)accept():在指定的端口等待客户端连接过来。在客户端连接过来之前,当前线程是处于挂起状态的,也就是说,如果没有客户端连接过来,这个方法不会执行结束。这个方法返回值是一个Socket类型的实例。
    3)close():结束监听,释放资源。
  • Socket类
    Socket类可以看做是两个端口之间的连接。两台电脑之间的通信使用的就是这个类。有两种途径来创建Socket类的实例。一种是前面说的,ServerSocket类的accpet()方法会返回一个Socket的实例;另一种是通过Socket类的构造方法创建。
    这时候是通过Socket进行数据传输的,Socket类中主要的方法有以下几个:
    1) 构造方法Socket(InetAddress,int):指定Socket需要连接的远程IP地址和端口。使用此构造方法创建出Socket实例,会连接到这个IP地址:端口号,并进一步可以使用这个IP地址:端口号进行数据传输。
    2) getInputStream():方法返回值是一个InputStream的实例,通过输入流可以读取信息。必须在建立连接后才能调用此方法。
    3) getOutputStream():方法的返回值是一个OutputStream的实例,通过输出流可以向远程计算机输入信息。同样,也必须在建立连接后才能调用此方法。
    4) close():关闭连接,释放资源。

4.服务端

  • 创建套接字描述符(socket)
  • 设置服务器的IP地址和端口号(需要转换为网络字节序的格式)
  • 将套接字描述符绑定到服务器地址(bind)
  • 将套接字描述符设置为监听套接字描述符(listen),等待来自客户端的连接请求,监听套接字维护未完成连接队列和已完成连接队列
  • 从已完成连接队列中取得队首项,返回新的已连接套接字描述符(accept),如果已完成连接队列为空,则会阻塞
  • 从已连接套接字描述符读取来自客户端的请求(read)
  • 向已连接套接字描述符写入应答(write)
  • 关闭已连接套接字描述符(close),回到第5步等待下一个客户端的连接请求

代码:

import java.io.BufferedReader;						// 引入需要使用的类
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class rw24 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			  ServerSocket ss = new ServerSocket(7777);
											// (1)在本机的7777端口监听
			  System.out.println("服务器端在7777端口监听……"); 
			  Socket s = ss.accept();		// (2)等待客户端连接到7777端口
			  // 如果没有客户端连接过来,accept()方法不会返回
			  System.out.println("已有客户端连接过来,开始进行通信……");
			  InputStream in = s.getInputStream();	// (3)得到输入流
			  OutputStream out = s.getOutputStream();// (4)得到输出流
			  PrintWriter pw = new PrintWriter(out);	
										// 使用PrintWriter向客户端输出数据
			  System.out.println("正在向客户端发送消息……");
			  pw.write("客户端,你好,这里是服务器端。\r\n");
			  pw.flush();				// 强制发送数据
			  System.out.println("向客户端发送消息完成。");
			  // 使用BufferedReader读取客户端发送来的数据
			  BufferedReader br = new BufferedReader(new InputStreamReader(in));
			  String response = br.readLine();
			  System.out.println("\n======下面是客户端发来的消息======");
			  System.out.println(response);
			  System.out.println("================================");
			  br.close();					// (5)调用close()方法释放资源
			  pw.close();
			  s.close();
			  ss.close();
		} catch (UnknownHostException e) {
			  System.out.println("无法找到相应的机器,错误信息。" + e.getMessage());
		} catch (IOException e) {
			 System.out.println("数据传输出现异常:" + e.getMessage());
		}
	}

}

编译结果如下图所示:
在这里插入图片描述

5.客户端

客户端:

  • 创建套接字描述符(socket)
  • 设置服务器的IP地址和端口号(需要转换为网络字节序的格式)
  • 请求建立到服务器的TCP连接并阻塞,直到连接成功建立(connect)
  • 向套接字描述符写入请求(write)
  • 从套接字描述符读取来自服务器的应答(read)
  • 关闭套接字描述符(close)
    urce=copy

代码:

import java.io.BufferedReader;					// 引入需要使用的类
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class rw25 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] addr = new byte[] { 127, 0, 0, 1 };		// 与本机进行通信
		try {
			InetAddress local = InetAddress.getByAddress(addr);
			Socket s = new Socket(local, 7777);
			InputStream in = s.getInputStream();
			OutputStream out = s.getOutputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String response = br.readLine();
			System.out.println("======下面是服务端发来的消息======");
			System.out.println(response);
			System.out.println("================================");
			System.out.println("正在向服务器端发送消息……");
			PrintWriter pw = new PrintWriter(out);
			pw.write("服务器你好,这里是客户端。");
			pw.flush();
			pw.close();
			br.close();
			s.close();
			System.out.println("向服务器端发送消息结束。");
		} catch (UnknownHostException e) {
			System.out.println("无法找到相应的机器,错误信息。" + e.getMessage());
		} catch (IOException e) {
			System.out.println("数据传输出现异常:" + e.getMessage());
		}

	}

}

在这里插入图片描述

6.文本聊天程序

  • 整个通信的过程如下:
    1) 服务器监听7777端口。
    2) 客户端连接服务器端的7777端口。
    3) 服务器端向客户端发送数据。
    4) 客户端收到数据,输出到控制台。
    5) 客户端向服务器端发送数据。
    6) 服务器端收到数据并输出到控制台。
    7) 服务器端和客户端关闭连接,释放资源。

服务器:
在这里插入图片描述
客户端:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Atishoo_13/article/details/82872894