您的位置:首页 > 编程语言 > Java开发

java-用java.net.Socket和java.net.ServerSocket实现简单的聊天程序

2017-03-17 11:25 1216 查看
java.net.Socket
java.net.ServerSocket
实现简单的聊天程序

思路是这样的:

假设用户A与用户B进行聊天,用户B端使用ServerSocket作为服务端,而用户A使用Socket与用户B进行通信。

这两个小程序需要运行在同一台电脑上,才能正常通信。

运行时一定要先运行
Server.class
再运行
Client.class


通过异常来控制程序逻辑不是首选方式,但想了很久也没想出其它方法
>.<


用户A的代码如下(
Client.java


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by DuanJiaNing on 2017/3/16.
*/
public class Client {

public static void main(String[] args) {
try {
//创建Socket连接到本机的2003端口
Socket socket = new Socket(InetAddress.getLocalHost(), 2003);
println("**********您正在和:" + InetAddress.getLocalHost().getHostAddress() + " 聊天***********\n" + "输入信息,按回车即可发送!输入quit可结束会话并关闭程序。");
OutputStream out = socket.getOutputStream();
out.write("Hello 在么?".getBytes());

//创建新线程负责打印接收到的消息
new Thread(new ClientThread(socket.getInputStream())).start();

//接收控制台输入
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//读取控制台输入,有输入且不为quit时进行发送
String line;
while ((line = bufr.readLine()) != null && !line.equals("quit")) {
out.write(line.getBytes());
}
//关闭套接字
//程序结束 这将导致ClientThread抛java.net.SocketException: Socket closed异常而结束(暂且就这样关闭这个线程)
socket.close();

} catch (Exception e) {
e.printStackTrace();
}
}

static class ClientThread implements Runnable {
InputStream input;

public ClientThread(InputStream in) {
this.input = in;
}

public void run() {
byte[] bytes = new byte[1024];
int len;
try {
//当收到消息时把消息打印到控制台
while ((len = input.read(bytes)) != -1) {
println(new String(bytes, 0, len));
}
} catch (Exception e) {
//当服务端或客户端结束会话时(输入quit时)会关闭socket从而抛出java.net.SocketException: Socket closed异常
//隐藏此异常不做处理让程序继续“正常”运行(正常结束)
if (!(e instanceof SocketException))
e.printStackTrace();
}
println("**********此次会话结束**********");
System.exit(0);
}
}

private static void println(String msg) {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
System.out.println(format.format(date) + msg);
}

}


用户B代码(服务端)(
Server.java


import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by DuanJiaNing on 2017/3/16.
*/
public class Server {

private static BufferedReader reader;

public static void main(String[] args) {

//监听本机(服务器)的2003端口
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(2003);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {

try {
println("************当前没有正在进行的会话***********");

//accept为阻塞时方法,当有连接时会返回连接着的socket对象
Socket socket = serverSocket.accept();
println("当前聊天对象来自:" + socket.getLocalAddress().getHostAddress() + "\n" + "输入信息,按回车即可发送!输入quit可结束此次会话。");

//创建新线程负责打印接收到的消息
InputStream in = socket.getInputStream();
new Thread(new ServerThread(in)).start();

//接收输入并发送给连接者
reader = new BufferedReader(new InputStreamReader(System.in));
String line;
OutputStream out = socket.getOutputStream();
while ((line = reader.readLine()) != null && !line.equals("quit")) {
out.write(line.getBytes());
}
//服务端主动结束会话
out.write("先不聊了。bye~".getBytes());

//关闭套接字
//程序结束 这将导致ServerThread抛java.net.SocketException: Socket closed异常而结束(暂且就这样关闭此次会话对应的线程)
socket.close();

} catch (Exception e) {
//当客户端主动结束会话(输入quit时),而服务端试图发送信息时会抛出java.net.SocketException: Software caused connection abort: socket write error
//借这个异常让服务端回到等待客户端接入状态
if (e instanceof SocketException) {
println("您的聊天对象已离线\n");
continue;
}
else
e.printStackTrace();
}
}
}

static class ServerThread implements Runnable {
InputStream input;

public ServerThread(InputStream in) {
this.input = in;
}

public void run() {
byte[] bytes = new byte[1024];
int len;
try {
//当收到消息时把消息打印到控制台
while ((len = input.read(bytes)) != -1) {
println(new String(bytes, 0, len));
}
} catch (Exception e) {
//当服务端或(输入quit时)会关闭socket从而抛出java.net.SocketException: Socket closed异常
//当服务端输入quit时隐藏此异常不做处理让程序继续运行(回到等待客户端接入的状态)
if (!(e instanceof SocketException)) {
e.printStackTrace();
}
}

}
}

private static void println(String msg) {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
System.out.println(format.format(date) + msg);
}
}


编译运行

分别编译Server.java,Client.java文件

javac Server.java
javac Client.java


先后运行Server.class和Client.class

java Server
java Client


此时可看到:



接下来进行简单对话后在服务端输入
quit
可看到:



此时客户端已经关闭,而服务端会循环阻塞在accept方法上。此时只需再次运行Client.class(在dos终端切换到Client.class文件所在路径后输入
java Client
)就能再次连接到服务端

服务端主动结束会话,此时时这样的:



有哪里可以改进的可以留言告诉我哦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: