目录
java网络编程
java.net.Socket
Socket(套接字)封装了TCP协议的通讯细节,使用它可以与服务端建立网络连接,并通过它获取两个流(一个输入一个输出),然后使用这两个流的读写操作完成与服务端的数据交互。
java.net.ServerSocket
ServerSocket运行在服务端,作用有两个:
1.向系统申请服务端口,客户端的Socket就是通过这个端口和服务端建立连接的。
2.监听服务端口,一旦一个客户端通过该端口建立连接则会自动创建一个Socket,并通过该Socket与客户端进行数据交互。
与服务端建立连接
客户端:
import java.io.IOException;
import java.net.Socket;
/**
* 聊天室客户端
*/
public class Client {
/*
java.net.Socket 套接字
Socket封装了TCP协议的通讯细节,我们通过它可以与远端计算机建立链接,
并通过它获取两个流(一个输入,一个输出),然后对两个流的数据读写完成
与远端计算机的数据交互工作。
我们可以把Socket想象成是一个电话,电话有一个听筒(输入流),一个麦克
风(输出流),通过它们就可以与对方交流了。
*/
private Socket socket;
/*构造方法,用来初始化客户端*/
public Client(){
try {
System.out.println("正在链接服务端...");
/*
实例化Socket时要传入两个参数
参数1:服务端的地址信息
可以是IP地址,如果链接本机可以写"localhost"
参数2:服务端开启的服务端口
我们通过IP找到网络上的服务端计算机,通过端口链接运行在该机器上
的服务端应用程序。
实例化的过程就是链接的过程,如果链接失败会抛出异常:
java.net.ConnectException: Connection refused: connect
*/
socket = new Socket("localhost",8088);
System.out.println("与服务端建立链接!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*客户端开始工作的方法*/
public void start(){
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}
服务端:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/*服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*服务端开始工作的方法*/
public void start(){
try {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
Socket提供了两个重要的方法:
OutputStream getOutputStream()
该方法会获取一个字节输出流,通过这个输出流写出的字节数据会通过网络发送给对方。
InputStream getInputStream()
通过该方法获取的字节输入流读取的是远端计算机发送过来的数据。
客户端代码:
import java.io.*;
import java.net.Socket;
/**
* 聊天室客户端
*/
public class Client {
/*
java.net.Socket 套接字
Socket封装了TCP协议的通讯细节,我们通过它可以与远端计算机建立链接,
并通过它获取两个流(一个输入,一个输出),然后对两个流的数据读写完成
与远端计算机的数据交互工作。
我们可以把Socket想象成是一个电话,电话有一个听筒(输入流),一个麦克
风(输出流),通过它们就可以与对方交流了。
*/
private Socket socket;
/*构造方法,用来初始化客户端*/
public Client(){
try {
System.out.println("正在链接服务端...");
/*
实例化Socket时要传入两个参数
参数1:服务端的地址信息
可以是IP地址,如果链接本机可以写"localhost"
参数2:服务端开启的服务端口
我们通过IP找到网络上的服务端计算机,通过端口链接运行在该机器上
的服务端应用程序。
实例化的过程就是链接的过程,如果链接失败会抛出异常:
java.net.ConnectException: Connection refused: connect
*/
socket = new Socket("localhost",8088);
System.out.println("与服务端建立链接!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*客户端开始工作的方法*/
public void start(){
try {
/*
Socket提供了一个方法:
OutputStream getOutputStream()
该方法获取的字节输出流写出的字节会通过网络发送给对方计算机。
*/
//低级流,将字节通过网络发送给对方
OutputStream out = socket.getOutputStream();
//高级流,负责衔接字节流与字符流,并将写出的字符按指定字符集转字节
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
//高级流,负责块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
//高级流,负责按行写出字符串,自动行刷新
PrintWriter pw = new PrintWriter(bw,true);
pw.println("你好服务端!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}
服务端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/* 服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*服务端开始工作的方法*/
public void start(){
try {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
可以理解为此操作是接电话,电话没响时就一直等。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
/*
Socket提供的方法:
InputStream getInputStream()
获取的字节输入流读取的是对方计算机发送过来的字节
*/
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"UTF-8");
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("客户端说:"+message);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
实现客户端循环发送消息给服务端
客户端代码:
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* 聊天室客户端
*/
public class Client {
/*
java.net.Socket 套接字
Socket封装了TCP协议的通讯细节,我们通过它可以与远端计算机建立链接,
并通过它获取两个流(一个输入,一个输出),然后对两个流的数据读写完成
与远端计算机的数据交互工作。
我们可以把Socket想象成是一个电话,电话有一个听筒(输入流),一个麦克
风(输出流),通过它们就可以与对方交流了。
*/
private Socket socket;
/*构造方法,用来初始化客户端*/
public Client(){
try {
System.out.println("正在链接服务端...");
/*
实例化Socket时要传入两个参数
参数1:服务端的地址信息
可以是IP地址,如果链接本机可以写"localhost"
参数2:服务端开启的服务端口
我们通过IP找到网络上的服务端计算机,通过端口链接运行在该机器上
的服务端应用程序。
实例化的过程就是链接的过程,如果链接失败会抛出异常:
java.net.ConnectException: Connection refused: connect
*/
socket = new Socket("localhost",8088);
System.out.println("与服务端建立链接!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*客户端开始工作的方法*/
public void start(){
try {
/*
Socket提供了一个方法:
OutputStream getOutputStream()
该方法获取的字节输出流写出的字节会通过网络发送给对方计算机。
*/
//低级流,将字节通过网络发送给对方
OutputStream out = socket.getOutputStream();
//高级流,负责衔接字节流与字符流,并将写出的字符按指定字符集转字节
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
//高级流,负责块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
//高级流,负责按行写出字符串,自动行刷新
PrintWriter pw = new PrintWriter(bw,true);
Scanner scanner = new Scanner(System.in);
while(true) {
String line = scanner.nextLine();
if("exit".equalsIgnoreCase(line)){
break;
}
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
/*
通讯完毕后调用socket的close方法。
该方法会给对方发送断开信号。
*/
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}
服务端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
*
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/*服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/* 服务端开始工作的方法*/
public void start(){
try {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
可以理解为此操作是接电话,电话没响时就一直等。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
/*
Socket提供的方法:
InputStream getInputStream()
获取的字节输入流读取的是对方计算机发送过来的字节
*/
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"UTF-8");
BufferedReader br = new BufferedReader(isr);
String message = null;
while((message = br.readLine())!=null) {
System.out.println("客户端说:" + message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
需要注意的几个点:
1.当客户端不再与服务端通讯时,需要调用socket.close()断开连接,此时会发送断开连接的信号给服务端。这时服务端的br.readLine()方法会返回null,表示客户端断开了连接。
2.当客户端链接后不输入信息发送给服务端时,服务端的br.readLine()方法是出于阻塞状态的,直到读取了一行来自客户端发送的字符串。
TCP的三次握手和四次挥手
客户端与服务端建立TCP连接时需要进行三次握手
双方断开连接时要进行四次挥手
多客户端连接
原因:服务端只调用一次accept方法,因此只有第一个客户端连接时服务端接受了连接并返回了Socket,此时可以与其交互。
而第二个客户端建立连接时,由于服务端没有再次accept,因此无法与其交互。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/*服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*服务端开始工作的方法*/
public void start(){
try {
while(true) {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
可以理解为此操作是接电话,电话没响时就一直等。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
/*
Socket提供的方法:
InputStream getInputStream()
获取的字节输入流读取的是对方计算机发送过来的字节
*/
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String message = null;
while ((message = br.readLine()) != null) {
System.out.println("客户端说:" + message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
添加循环操作后,发现依然无法实现。原因在于:外层while循环里面嵌套了一个内层循环(循环读取客户端发送消息),而循环执行机制决定了里层循环不结束,外层循环则无法进入第二次操作。
使用多线程实现多客户端连接服务端
服务端代码改造:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
*
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/*服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/* 服务端开始工作的方法*/
public void start(){
try {
while(true) {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
可以理解为此操作是接电话,电话没响时就一直等。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
//启动一个线程与该客户端交互
ClientHandler clientHandler = new ClientHandler(socket);
Thread t = new Thread(clientHandler);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
/**
* 定义线程任务
* 目的是让一个线程完成与特定客户端的交互工作
*/
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket = socket;
}
public void run(){
try{
/*
Socket提供的方法:
InputStream getInputStream()
获取的字节输入流读取的是对方计算机发送过来的字节
*/
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String message = null;
while ((message = br.readLine()) != null) {
System.out.println("客户端说:" + message);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
实现服务端发送消息给客户端
在服务端通过Socket获取输出流,客户端获取输入流,实现服务端将消息发送给客户端。
这里让服务端直接将客户端发送过来的消息再回复给客户端来进行测试。
服务端代码:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class Server {
/**
* 运行在服务端的ServerSocket主要完成两个工作:
* 1:向服务端操作系统申请服务端口,客户端就是通过这个端口与ServerSocket建立链接
* 2:监听端口,一旦一个客户端建立链接,会立即返回一个Socket。通过这个Socket
* 就可以和该客户端交互了
* 我们可以把ServerSocket想象成某客服的"总机"。用户打电话到总机,总机分配一个
* 电话使得服务端与你沟通。
*/
private ServerSocket serverSocket;
/*服务端构造方法,用来初始化*/
public Server(){
try {
System.out.println("正在启动服务端...");
/*
实例化ServerSocket时要指定服务端口,该端口不能与操作系统其他
应用程序占用的端口相同,否则会抛出异常:
java.net.BindException:address already in use
端口是一个数字,取值范围:0-65535之间。
6000之前的的端口不要使用,密集绑定系统应用和流行应用程序。
*/
serverSocket = new ServerSocket(8088);
System.out.println("服务端启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*服务端开始工作的方法*/
public void start(){
try {
while(true) {
System.out.println("等待客户端链接...");
/*
ServerSocket提供了接受客户端链接的方法:
Socket accept()
这个方法是一个阻塞方法,调用后方法"卡住",此时开始等待客户端
的链接,直到一个客户端链接,此时该方法会立即返回一个Socket实例
通过这个Socket就可以与客户端进行交互了。
可以理解为此操作是接电话,电话没响时就一直等。
*/
Socket socket = serverSocket.accept();
System.out.println("一个客户端链接了!");
//启动一个线程与该客户端交互
ClientHandler clientHandler = new ClientHandler(socket);
Thread t = new Thread(clientHandler);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
/**
* 定义线程任务
* 目的是让一个线程完成与特定客户端的交互工作
*/
private class ClientHandler implements Runnable{
private Socket socket;
private String host;//记录客户端的IP地址信息
public ClientHandler(Socket socket){
this.socket = socket;
//通过socket获取远端计算机地址信息
host = socket.getInetAddress().getHostAddress();
}
public void run(){
try{
/*
Socket提供的方法:
InputStream getInputStream()
获取的字节输入流读取的是对方计算机发送过来的字节
*/
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(isr);
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);
String message = null;
while ((message = br.readLine()) != null) {
System.out.println(host + "说:" + message);
//将消息回复给客户端
pw.println(host + "说:" + message);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
客户端代码:
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* 聊天室客户端
*/
public class Client {
/*
java.net.Socket 套接字
Socket封装了TCP协议的通讯细节,我们通过它可以与远端计算机建立链接,
并通过它获取两个流(一个输入,一个输出),然后对两个流的数据读写完成
与远端计算机的数据交互工作。
我们可以把Socket想象成是一个电话,电话有一个听筒(输入流),一个麦克
风(输出流),通过它们就可以与对方交流了。
*/
private Socket socket;
/*构造方法,用来初始化客户端*/
public Client(){
try {
System.out.println("正在链接服务端...");
/*
实例化Socket时要传入两个参数
参数1:服务端的地址信息
可以是IP地址,如果链接本机可以写"localhost"
参数2:服务端开启的服务端口
我们通过IP找到网络上的服务端计算机,通过端口链接运行在该机器上
的服务端应用程序。
实例化的过程就是链接的过程,如果链接失败会抛出异常:
java.net.ConnectException: Connection refused: connect
*/
socket = new Socket("localhost",8088);
System.out.println("与服务端建立链接!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*客户端开始工作的方法*/
public void start(){
try {
/*
Socket提供了一个方法:
OutputStream getOutputStream()
该方法获取的字节输出流写出的字节会通过网络发送给对方计算机。
*/
//低级流,将字节通过网络发送给对方
OutputStream out = socket.getOutputStream();
//高级流,负责衔接字节流与字符流,并将写出的字符按指定字符集转字节
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
//高级流,负责块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
//高级流,负责按行写出字符串,自动行刷新
PrintWriter pw = new PrintWriter(bw,true);
//通过socket获取输入流读取服务端发送过来的消息
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"UTF-8");
BufferedReader br = new BufferedReader(isr);
Scanner scanner = new Scanner(System.in);
while(true) {
String line = scanner.nextLine();
if("exit".equalsIgnoreCase(line)){
break;
}
pw.println(line);
line = br.readLine();
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
/*
通讯完毕后调用socket的close方法。
该方法会给对方发送断开信号。
*/
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}