这里我们通过一个用户登录的例子来学习基于 TCP 协议的 Socket 通信。
先通过下面一系列的图看了解一下Socket通信原理吧!
Socket通信模型
ServerSocket 构造器和成员方法
1、ServerSocket 构造方法
讲解:
①下面的backlog(积压的意思是指服务端同时允许和多少个客户端进行通信的数量)
②下面的第4个构造方法该构造方法就是在第三种构造方法的基础上,还制定了相关的IP地址,这种情况适用于计算机上有多块网卡和多个IP的情况,我们可以明确规定ServerSocket在那块网卡或者IP地址上等待客户的连接请求,显然对于只有一块网卡的情况我们就不用专门指定了。
2、ServerSocket 成员方法
Socket 构造器和成员方法
1、Socket 构造器
2、Socket 成员方法
一个服务端和支持多个客户端的对话demo
代码如下:
1、server.java
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* 基于TCP协议的Socket通信,实现用户登录
* 服务端
* @autho 196432
* @date 2017/12/4 下午7:37
*/
public class Server {
public static void main(String args[]) {
try {
//1、创建一个服务端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = null;
//记录客户端的数量
int count = 0;
//2、调用accept方法开始监听,等待客户端的连接
System.out.println("***服务端即将启动,等待客户端的连接****");
//循环监听等待客户端的连接
while(true) {
//调用accept()方法开始监听,等待客户端的连接
socket = serverSocket.accept();
//创建一个新的线程
ServerThread serverThread = new ServerThread(socket);
//启动线程
serverThread.start();
count ++;//统计客户端的数量
System.out.println("客户端的数量:"+count);
InetAddress inetAddress = socket.getInetAddress();
System.out.println("当前客户端的IP:"+inetAddress.getHostAddress());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、ServerThread.java
import java.io.*;
import java.net.Socket;
/**
* 服务器线程处理类
* @author 196432
* @date 2017/12/4 下午8:32
*/
public class ServerThread extends Thread {
//本线程相关的Socket
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
//线程执行操作,响应客户端的请求
public void run() {
InputStream inputStream = null;//字符输入流
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
OutputStream outputStream = null;
PrintWriter printWriter = null;
try {
//获取输入流,并读取客户端信息
inputStream = socket.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);//将字节流转换成字符流
bufferedReader = new BufferedReader(inputStreamReader);//为字符流添加缓存
String info = null;
while((info = bufferedReader.readLine()) != null) {
System.out.println("我是服务器,我接收到客户端发过来的消息是:"+info);
}
socket.shutdownInput();//关闭输入流(解释:因为把从客户端发过来的消息已经读完了,所以关闭)
//获取输出流,响应客户端的请求
outputStream = socket.getOutputStream();//获得往socket里面写数据的输出流
printWriter = new PrintWriter(outputStream);
printWriter.write("欢迎您!");
printWriter.flush();//刷新缓存
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
if(bufferedReader != null) {
bufferedReader.close();
}
if(outputStream != null) {
outputStream.close();
}
if(inputStreamReader != null) {
inputStreamReader.close();
}
if(inputStream != null) {
inputStream.close();
}
if(socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、Client.java
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端
* @author 196432
* @date 2017/12/4 下午7:37
*/
public class Client {
public static void main(String args[]) {
try {
//1、创建客户端Socket,指定要连接的服务器地址和端口
Socket socket = new Socket("localhost",8888);
//2、获取输出流,向服务器端发送信息
OutputStream outputStream = socket.getOutputStream();//字节输出流
PrintWriter printWriter = new PrintWriter(outputStream);//将输出流包装为打印流
Scanner scanner = new Scanner(System.in);
String s=new String(scanner.nextLine());
printWriter.write("用户名:Tom;密码:123456");
printWriter.flush();//刷新缓存,输出信息
socket.shutdownOutput();//关闭输出流
//3、获取输入流,并读取服务器的响应信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String info = null;
while((info = bufferedReader.readLine()) != null) {
System.out.println("我是客户端,我接收到服务器发过来的信息是:"+info);
}
//4、 关闭资源
printWriter.close();
bufferedReader.close();
inputStream.close();
outputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}