基于TCP原理Socket编程模拟多个客户端访问服务端

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40301026/article/details/88649554

利用TCP原理来模拟C/S模型,实现多个客户端访问服务器端。

主要是通过在服务端实现多线程来实现。

主要步骤:

              服务器端:

1.创建服务器端,指定端口。

2.调用accept方法,.阻塞式等待客户端连接

3.通过IO流拿到服务端的请求数据,并且对其分析。

4.再通过IO流把分析好后的数据发送出去。(对客户端的响应)

5.释放此次和这个客户端有关的资源。

2,3,4,5是在新的线程里运行,所以可以有多个客户端去请求访问。

               客户端:

1.创建一个客户端,指定要访问呢的IP地址和端口号。

2.建立连接后,通过IO流向服务器端发送请求数据。

3.通过IO流,接收到服务端的响应数据。

4.释放此次的相关资源,结束请求。

代码:

package cn.liu.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

/**
 * 模拟:服务器端
 * 1.可以支持访问响应
 * 2.也可以支持多个客户端访问
 * @author Administrator
 */

public class Server03{
	private ServerSocket server;
	private int port;
	
	public Server03(int port) throws Exception {
		this.port = port;
		this.server = new ServerSocket(port);
	}
	
	//服务器对客户端的响应
	public void work() throws Exception {
		/**
		 * 错误:这只会有一个连接,一直在循环单线程内容。
		 * Socket client = server.accept();//阻塞式等待连接
		 * System.out.println("连接成功");
		 * while(true){
		 * new Thread(new response(client)).start();
		 * }
		 */
		while(true) {
		Socket client = server.accept();//阻塞式等待连接
		System.out.println("连接成功");
		new Thread(new response(client)).start();
	    }
	}
}


//Server的响应封装为一个类,方便多线程。
class response implements Runnable{
	private Socket client;
	
	public response(Socket client) {
		super();
		this.client = client;
	}

	@Override
	public void run() {
		try {
			//拿到客户端的请求数据
			DataInputStream is = new DataInputStream(client.getInputStream());

			//对请求数据进行处理
			String data = is.readUTF();
			String[] datas = data.split("&&");
			//String[] datas = is.readUTF().split("&&");
		
			String str = null;
			if(datas[0].equals("liu") && datas[1].equals("123456")) {
				str = "用户名正确!\n密码正确!\n欢迎登录!";
			}else {
				str = "用户名或密码错误!";
			}
			
			//对请求数据做出响应,返回给客户端
			DataOutputStream os = new DataOutputStream(client.getOutputStream());
			os.writeUTF(str);
			os.flush();
			
			//关闭相关资源
			is.close();
			os.close();
			client.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
package cn.liu.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * 模拟登录:
 * 1.可以支持访问响应
 * 2.也可以支持多个客户端访问
 * @author Administrator
 */
public class Client03{
	private String ip;
	private int serverPort;
	private Socket client;

	public Client03(String ip, int serverPort) throws Exception{
		super();
		this.ip = ip;
		this.serverPort = serverPort;
		this.client = new Socket(ip,serverPort);
	}

	public void request() throws Exception {
		//向服务器发送请求数据
		Scanner storage = new Scanner(System.in);
		System.out.println("输入你的名字:");
		String uname = storage.nextLine();
		System.out.println("输入你的密码:");
		String upassword = storage.nextLine();
		
		DataOutputStream os = new DataOutputStream(client.getOutputStream() );
		os.writeUTF(uname+"&&"+upassword);
		os.flush();
		
		//得到服务的响应数据
		DataInputStream is = new DataInputStream(client.getInputStream());
		String str = null;
		str = is.readUTF();
		System.out.println(str);
		
		//关闭IO流,关闭连接
		os.close();
		is.close();
		client.close();
	}
}

测试:

//一个服务端
public static void main(String[] args) throws Exception {
		System.out.println("----------------Server-------------");
		Server03 ss = new Server03(8848);
		ss.work();
	}
//多个客户端
public static void main(String[] args) throws Exception {
		System.out.println("----------------client-------------");
		Client03 aa = new Client03("Dick",8848);
		aa.request();
	}


public static void main(String[] args) throws Exception {
		System.out.println("----------------client-------------");
		Client03 bb = new Client03("Dick",8848);
		bb.request();
	}

 效果:

自己思路方面遇到的问题:

1.如何判断这个输入输出的方向,即:IO流神魔时候用输出神魔时候输入。

最后发现输入就是:写到IO流中,通过内存写向硬盘或(服务器端)。输出就是通过内存从硬盘(服务器端)中拿到数据。

2.写完后程序一直出错,最后发现是服务器端有错。

//服务器对客户端的响应

public void work() throws Exception {

/**

* 错误:这只会有一个连接,一直在循环单线程内容。

* Socket client = server.accept();//阻塞式等待连接

* System.out.println("连接成功");

* while(true){

* new Thread(new response(client)).start();

* }

*/

while(true) {

Socket client = server.accept();//阻塞式等待连接

System.out.println("连接成功");

new Thread(new response(client)).start();

}

主要问题还是自己对这个Socket client = server.accept();//阻塞式等待连接。

阻塞式没有理解到位。如果没有建立连接就一直会等,现在要实现多线程支持多个客户端访问,那就也要多个连接,所以Socket client = server.accept(()也要放进while()循环体。

猜你喜欢

转载自blog.csdn.net/qq_40301026/article/details/88649554