一个简单的消息群里的聊天室功能,虽然功能不强大,主要是为了给初学者梳理梳理一下思路。希望能够帮到有需要的人,大家一同共同学习,互相帮助。’
package mysocket;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端
* @author DELL
*
*/
public class Client {
/*
* Socket 套接字
* 封装了TCP协议连接和通讯的细节,使用它与远端计算检疫连接后可以通过两条流来实现
* 相互的数据交换
*/
private Socket socket;
//主方法
public static void main(String[] args) {
Client client = new Client();
client.start();
}
//构造方法,初始化程序
public Client() {
/*
* 实例化Socket
* 实例Socket需要传入两个参数
* Socket(String host, int port)
* 1:服务端计算机地址信息(IP)
* 2:服务端程序申请的服务端口
*
* 实例化过程就是与服务端建立连接的过程,
* 若指定的IP地址与端口无效时,这里实例化
* 就会抛出异常。因此我们在实例化的同时要处理
* 异常。
*
*/
try {
System.out.println("正在连接服务端...");
socket = new Socket("localhost",8088);
System.out.println("服务端连接成功!");
} catch (Exception e) {
}
}
//运行程序的方法
public void start() {
/*
* 这里执行与服务端进行消息交互的方法。
* 如果希望向服务端发送消息我们需要通过Socket
* OutputStream getOnputStream()
* 方法获取输出流
*/
try {
/*
* 串联一个流连接,提升效率
*/
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);//此处注意参数true,若不添加此方法我们需要频繁调用flush方法来保证消息的及时性。
Scanner scan = new Scanner(System.in);
while(true) {
String line = scan.nextLine();
pw.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package mysocket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端
* @author DELL
*
*/
public class Server {
/*
* java.net.ServerSocket
* 运行在服务端的ServerSocket主要有两个作用
* 1:向系统申请服务端口,客户端就是通过这个端口与服务端建立连接的
* 2:监听服务端口,一旦客户端通过该端口连接则马上会实例化一个
* Socket与之反应。服务端就可以通过这个Socket与客户端进行交互了。
*
* 如果把Socket比喻为电话,那么ServerSocket可以想象为是总机。
*/
private ServerSocket server;
public static void main(String[] args) {
Server server = new Server();
server.start();
}
//构造方法,初始化程序
public Server() {
try {
/*
* 实例化ServerSocket的同时要制定服务端口。
* 当该端口已经被系统其它程序所使用时,会抛出地址被占用的异常。
* 因此我们也需要使用异常处理机制处理一下。
*/
System.out.println("正在启动服务端...");
server = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
}
}
public void start() {
while(true) {
/*
* ServerSocket提供的方法:
* Socket accept();
* 该方法是一个阻塞方法,执行后服务端开始监听服务端口,知道一个客户端连接为止,
* 这时该方法会返回一个Socket实例,通过该实例即可以与客户端进行通讯了。
* 每次调用该方法都会导致服务端阻塞,等待一个客户端的连接。
*/
try {
System.out.println("正在等待客户端连接...");
Socket socket = server.accept();
//此时在等待一个窗口为8088的客户端连接,我们要实现群聊效果,因此需要使用到多线程。
MyRunnable client = new MyRunnable(socket);
Thread thread = new Thread(client);
thread.start();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
class MyRunnable implements Runnable{
private Socket socket;
String host;
public MyRunnable(Socket socket) {
this.socket = socket;
/*
* getInetAddress()返回对象包含远程计算机的IP地址
* InetAddress.getHostAddress()返回对象与该地址的文本表示。
*/
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();
System.out.println("IP:"+host+"连接成功!");
}
public void run() {
try {
//在这里我也同样通过Socket提供的方法实现与客户端的交互
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"utf-8");
BufferedReader br = new BufferedReader(isr);
String str = null;
/*
* br.readLine()读取客户端发送过来的一行字符串的操作中
* 当客户端断开连接时,客户端系统不同
* 这里的表现也不同
* 通常windows的客户端断开时,readLine方法会直接抛出异常
* linux的客户端断开连接时,readLine方法的返回值通常为null
*/
while((str = br.readLine())!=null) {
System.out.println("IP:"+host+"说:"+str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}