Socket是一个有效的网络通信的工具,下面这个简单例子给大家演示一下如何使用Socket来做服务器与客户端之间的通信
客户端代码
/**
* @author Jian
* 客户端
*/
public class Client {
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口,本机也可以为localhost
Socket socket= new Socket("127.0.0.1", 1344);
//2.获取输出流,向服务器端发送登录信息
OutputStream os = socket.getOutputStream();//字节输出流
*//**
* 可以装饰为打印流,也可以采用下装饰为字符输出流,使用缓冲来写入
* PrintWriter pw = new PrintWriter(os);//输出流包装为打印流
*//*
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter pw = new BufferedWriter(osw);
pw.write("用户名:admin;密码:123");
pw.flush();//调用flush()刷新缓存
//关闭输出流
socket.shutdownOutput();
//3.获取输入流,读取服务器端相应信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);//字节流转换为字符流
BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取服务器端响应信息
System.out.println("服务器端信息:"+info);
}
//4.关闭相关资源
br.close();
isr.close();
is.close();
pw.close();
osw.close();
os.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
服务器端代码
/**
* @author Jian
* 基于TCP协议的Socket通信,实现用户登录
* 服务器端
*/
public class Server {
/*public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(1344);
//2.调用accept()方法,等待客户端的连接
System.out.println("-----服务器即将启动,等待客户端连接");
Socket socket = serverSocket.accept();//阻塞式
//3.获取输入流,并读取客户端信息
InputStream is = socket.getInputStream();//字节输入流
InputStreamReader isr = new InputStreamReader(is);//字节流转换为字符流
BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取
System.out.println("服务器收到的客户端数据"+info);
}
// socket.shutdownInput();//关闭输入流
//4.获取输出流,响应客户端的请求
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("Welcome!");
pw.flush();//刷新缓存
//5.关闭相关资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
在客户端的代码中,发送完数据后需要调用shutdownOutput()来告诉服务器端已经发送完毕,这样会使得接下来再利用输出流来向服务器发送信息,所以我们可以将代码稍加修改
服务器端
DataInputStream dis = new DataInputStream(is);
int flag = 0;
while(true){//循环读取
flag = br.read();
System.out.println(flag);
if(flag==1){
String data = dis.readUTF();
System.out.println(data);
}
break;
}
客户端
DataOutputStream dos = new DataOutputStream(os);
pw.write(1);
pw.flush();
dos.writeUTF(("用户名:admin;密码:123"));
dos.flush();//调用flush()刷新缓存
//关闭输出流
//socket.shutdownOutput();
这里我们可以先约定好通信协议,传数字代表的含义,然后可以在服务器端的监听中调用别的方法,使用DataInputStream的readUTF()方法可以读取整段文字,你可以自行设计方法,来避免shutdownIn/Output()后造成无法读写的问题。
尝试一下多线程下的Socket通信
客户端没有什么变化,只要让Server保持死循环监听,每有一个客户端连接进来,就开启一个线程,并在这个线程里与客户端进行通信,具体代码如下:
服务器端
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(1344);
//2.调用accept()方法,等待客户端的连接
System.out.println("-----服务器即将启动,等待客户端连接");
Socket socket = null;
//記錄客戶端數量
int count = 0;
while(true){
socket = serverSocket.accept();//阻塞式
//創建一個新的線程
ServerThread serverThread = new ServerThread(socket);
serverThread.start();
count++;
System.out.println("客戶端數量:"+count);
InetAddress address = socket.getInetAddress();
System.out.println("當前客戶端的IP:"+address.getHostAddress());
}
// serverSocket.close();
线程类
/**
* @author Jian
* 服务器端线程处理类
*/
public class ServerThread extends Thread{
//和本线程相关的Socket
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
//线程的操作,响应客户端请求
public void run(){
InputStreamReader isr=null;
InputStream is=null;
BufferedReader br=null;
OutputStream os=null;
PrintWriter pw=null;
//3.获取输入流,并读取客户端信息
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);//字节流转换为字符流
br = new BufferedReader(isr);//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取
System.out.println("服务器收到的客户端数据"+info);
}
socket.shutdownInput();//关闭输入流
//4.获取输出流,响应客户端的请求
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("Welcome!");
pw.flush();//刷新缓存
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//5.关闭相关资源
try {
if(pw!=null)
pw.close();
if(os!=null)
os.close();
if(br!=null)
br.close();
if(isr!=null)
isr.close();
if(is!=null)
is.close();
if(socket!=null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}