Socket通信

基于TCP协议,面向连接,效率低,但安全性高

1.例子:建立服务器与客户端,实现通信(该例子服务器只可以接受一个客户端连接)

/*
	 * 服务器端serverSocket
	 */
	@Test
	public void test5() throws IOException {
		ServerSocket server=new ServerSocket(9999);      
		Socket socket=server.accept();        //返回服务器与客户端的连接Socket(阻塞式,无连接不向下运行)
		System.out.println("创建一个连接!");      //此时可直接用浏览器访问localhost:9999
		String msg="你好!欢迎访问";
		DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
		dos.writeUTF(msg);
		dos.flush();
		dos.close();
	}
	/*
	 * 客户端socket(与UDP不同,不用指定客户端端口)
	 */
	@Test
	public void test6() throws UnknownHostException, IOException {
		Socket client=new Socket("localhost",9999);   //指定的式服务器的ip和端口,此时就以建立连接
		DataInputStream dis=new DataInputStream(client.getInputStream());
		String s=dis.readUTF();
		System.out.println(s);
	}

2.例子:聊天室(实现群聊和私聊,每个用户登录时的提示)

1)服务器类:

public class Server2 {
	
	//用来统一管理所有的客户端连接
	List<MySocket> list=new ArrayList<>();
	
	/*
	 * 启动服务器:
	 * 1.建立服务器
	 * 2.无限循环等待接受连接,若连接上将其将入管理list,建立新的线程
	 */
	public void startt() throws IOException {
		ServerSocket server=new ServerSocket(8888);
		while(true) {
			Socket client=server.accept();
			MySocket my=new MySocket(client);
			list.add(my);
			new Thread(my).start();
		}
	}
	
	public static void main(String[] args) {
		try {
			new Server2().startt();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/*
	 * 内部客户端连接类
	 */
	class MySocket implements Runnable{
		//每个客户端了连接都有一个自己的输入输出流
		boolean flag=true;
		DataInputStream dis;
		DataOutputStream dos;
		String name;
		
		public MySocket(Socket client) {
			try {
				dis=new DataInputStream(client.getInputStream());
				dos=new DataOutputStream(client.getOutputStream());
				name=dis.readUTF();
				send("欢迎"+name+"登录");    //调用自己通道的send方法,发送给自己的客户端
				sendOthers(name+"进入聊天室");   //通知其他用户该用户进入
			} catch (IOException e) {
				finish();
			}
			
		}
		
		public void finish() {
			flag=false;
			CloseUtils.closeAll(dis,dos);
			list.remove(this);    //若出现错误,将自己从管理器中移除
		}
		
		
		public String recieve() {
			String s=null;
			try {
				s=dis.readUTF();
			} catch (IOException e) {
				finish();

			}
			return s;
		}
		
		public void send(String s) {
			try {
				dos.writeUTF(s);
				dos.flush();
			} catch (IOException e) {
				finish();
			}
			
		}
		
		
		/*
		 * 分为群发和私聊
		 */
		public void sendOthers(String s) {
			if(s.startsWith("@")) {
				String name=s.substring(1,s.indexOf(":"));
				String content=s.substring(s.indexOf(":")+1);
				for(MySocket temp:list) {
					if(temp.name.equals(name)) {
						temp.send("[私聊]"+content);
						break;
					}
					
				}
			}else {
				for(MySocket temp:list) {
					if(temp==this) continue;
					temp.send("[群发]"+s);
				}
			}
			
			
		}
		
		

		@Override
		public void run() {
			while(flag) {
				String s=recieve();
				sendOthers(s);
			}
		}
	}

}

2)客户端类 

public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket client=new Socket("localhost", 8888);
		System.out.println("请输入姓名");
		
		String name=new Scanner(System.in).nextLine();
		
		//如果不使用多线程,客户端只有发送完信息以后才可以接受信息
		
		
		new Thread(new Send(client,name)).start();
		
		new Thread(new Recieve(client)).start();
		
	}

}

3)客户端中接受线程 

public class Recieve implements Runnable{
	
	DataInputStream dis;
	
	boolean isRunning=true;
	
	public Recieve(Socket client) {
		try {
			dis=new DataInputStream(client.getInputStream());
		} catch (IOException e) {
			isRunning=false;
			CloseUtils.closeAll(dis);

		}
	}
	
	public String recieve() {
		String msg="";
		try {
			msg=dis.readUTF();
		} catch (IOException e) {
			isRunning=false;
			CloseUtils.closeAll(dis);
		}
		return msg;
	}

	@Override
	public void run() {
		while(isRunning) {
			System.out.println(recieve());
		}
	}

}

4)客户端中发送线程 

public class Send implements Runnable{
	//控制台输入流
	BufferedReader br;
	//socket输出流
	DataOutputStream dos;
	
	boolean isRunning=true;
	
	public Send(Socket client,String name) {
		br=new BufferedReader(new InputStreamReader(System.in));
		try {
			dos=new DataOutputStream(client.getOutputStream());
			dos.writeUTF(name);
			dos.flush();
		} catch (IOException e) {
			isRunning=false;
			CloseUtils.closeAll(br,dos);
		}
	}
	public void send() {
			String s;
			try {
				s = br.readLine();
			} catch (IOException e) {
				s="";
			}
			if(s!=null||!s.equals("")) {
				try {
					dos.writeUTF(s);
					dos.flush();
				} catch (IOException e) {
					isRunning=false;
					CloseUtils.closeAll(br,dos);
				}
			}
	}
	@Override
	public void run() {
		while(isRunning) {
			send();
		}
	}
	
	
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值