基于TCP协议(面向连接,安全可靠)
步骤:
服务器端:
创建ServeSocket(int port)对象 ///指定端口
在Socket上监听客户端的连接请求
阻塞,等待连接建立
接收并处理请求信息
将处理结果返回客户端
关闭流和Socket对象
客户端:
创建Socket(String host,int port)对象 ///指定服务器位置与端口
向服务器发送连接请求
向服务器发送服务请求
接收服务结果
关闭流和Socket对象
模拟登陆系统底层原理:
服务器端:
public class LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
ServerSocket server=new ServerSocket(8888);//创建ServerSocket对象
Socket client1=server.accept();//在Socket上监听客户端
System.out.println("一个客户端建立连接");
DataInputStream dis=new DataInputStream(client1.getInputStream() );
String data=dis.readUTF();//使用DataInputStream数据输入流得到客户端发送的用户名密码数据
String []dataArray=data.split("&");
System.out.println("你的用户名为"+dataArray[0]);
System.out.println("你的密码为"+dataArray[1]);//将得到的字符串以"&"为界限分割
//分析数据并且双向输出,返回结果给客户端
DataOutputStream dos=new DataOutputStream(client1.getOutputStream());
if(dataArray[0].equals("xiaojiehang")&&dataArray[1].equals("xjh")){
dos.writeUTF("登陆成功");
}else{dos.writeUTF("账号密码不匹配");}
dos.flush();
dos.close();
dis.close();
client1.close();
//server.close(); //服务器一般不关闭,除了进行维护
}
}
客户端:
public class LoginClient {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
Scanner scanner=new Scanner(System.in);
// BufferedReader br=new BufferedReader(new InputStreamReader(System.in));得到键盘输入的其他方式
System.out.println("输入用户名:");
String name=scanner.nextLine();
System.out.println("输入密码:");
String password=scanner.nextLine();//得到输入的数据
Socket client=new Socket("localhost",8888);//建立连接,连接服务器的地址与端口
DataOutputStream dos=new DataOutputStream( client.getOutputStream() );//尽量选用Data流,如果数据是Java的基本数据类型
dos.writeUTF(name+"&"+password);
dos.flush();
//得到服务器的返回值,双向传递
DataInputStream dis=new DataInputStream( client.getInputStream() );//数据输入流为client插座的输入流
String result=dis.readUTF();
System.out.println(result);
dos.close();//关闭资源
dis.close();
client.close();
}
}
改造成多线程(多个客户端)
将服务器端改造成多线程:
Socket client1多次监听客户端的连接请求
public class LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
ServerSocket server=new ServerSocket(8888);//创建ServerSocket对象
boolean isrunning=true;
while(isrunning) {//是服务器一直运行不关闭,每次监听为一次线程
Socket client1 = server.accept();//在Socket上监听
System.out.println("一个客户端建立连接");
new Thread(new channel(client1)).start();
}
server.close();
}
static class channel implements Runnable{
private DataInputStream dis;
Socket client1;
DataOutputStream dos;
public channel(Socket client1) throws IOException {
this.client1=client1;
dis=new DataInputStream(client1.getInputStream() );
dos=new DataOutputStream(client1.getOutputStream());
}
public String receivedata() {//接收数据
String data=" ";
try {
data = dis.readUTF();//得到用户名密码数据
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
public void senddata(String s) {//发送数据
try {
dos.writeUTF(s);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void release(){//释放资源,目的是使run方法更简洁
try {
if(dos!=null){
dos.close();}
if(dis!=null){
dis.close();}
} catch (IOException e) {
e.printStackTrace();
}
if(client1!=null){
try {
client1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
String []dataArray=receivedata().split("&");
System.out.println("你的用户名为"+dataArray[0]);
System.out.println("你的密码为"+dataArray[1]);//将得到的字符串以"&"为界限分割
if(dataArray[0].equals("xiaojiehang")&&dataArray[1].equals("xjh")){
senddata("登陆成功");
}else{senddata("账号密码不匹配");} //分析数据并且双向输出,返回结/果给客户端
release();
//server.close(); //服务器一般不关闭,除了进行维护
}
}
}
将客户端收发数据封装:
public class LoginClient {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
Scanner scanner=new Scanner(System.in);
System.out.println("输入用户名:");
String name=scanner.nextLine();
System.out.println("输入密码:");
String password=scanner.nextLine();
Socket client=new Socket("localhost",8888);//建立连接,连接服务器的地址与端口
new csend(client).send(name+"&"+password);
new creceive(client).receive();
client.close();
}
static class csend{//用于发送信息
DataOutputStream dos;
Socket client;
public void send(String s){
try {
dos.writeUTF(s);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public csend(Socket client) throws IOException {//构造函数,传入插座client,以及构造一个数据输出流用于发送数据
this.client=client;
try {
dos=new DataOutputStream( client.getOutputStream() );//尽量选用data流
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() throws IOException {
dos.close();
}
}
static class creceive{//用于接收信息
//得到服务器的返回值
Socket client;
DataInputStream dis;
String result=null;
public creceive(Socket client) throws IOException {
this.client=client;
try {
dis=new DataInputStream( client.getInputStream() );
} catch (IOException e) {
e.printStackTrace();
}
}
public void receive() throws IOException {
try {
result = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(result);
}
public void close() throws IOException {
dis.close();
}
public String getResult() {
return result;
}
}
}