专门做学校政府的网站/百度站点
标题:TCP编写的聊天室
一、服务器端编程步骤:
- 1.创建ServerSocket(int port)对象
- 2.在Socket上监听客户端的连接请求
- 3.阻塞、等待连接的建立
- 4.接收并处理请求信息
- 5.将处理结果返回给客户端
- 6.关闭流和Socket对象
二、客户端编程步骤:
- 1.创建Socket(String host,int port)对象
- 2.向服务器发送连接请求
- 3.向服务器发送服务请求
- 4.接收服务结果
- 5.关闭流和Socket对象
三、实现通信
原理:多个客户端将消息发送个服务器,服务器接收后反馈给客户端
1)第一步,首先服务器端,客户端建立连接
2)第二步,客户端发送消息给服务器端,服务器端反馈客户端的消息
3)第三步,服务器端需使用while循环实现建立多次连接,从而可以实现多个客户端与一个服务器端通信,注意:此处需使用多线程,否则实现不了多个客户端与服务器端的同时通信
while(flag) {//2.在Socket上监听客户端的连接请求client=server.accept();//3.阻塞、等待连接的建立 System.out.println("建立好了一次连接"); //这样写必须等第一个客户端建立好了连接,发送了账号、密码,才能接收其他的客户端//使用线程的原因,是因为可以不用等待线程体中的代码运行完,再次接收客户端的请求new Thread(new Channel(client,list)).start();}
4)可以不要。在服务器的多线程中测试输入的账号密码正确与否,正确就开启通信,错误则关闭客户端。若此判断未在多线程里面,则实现不了客户端的同时登入
5)实现客户端接收消息,与发送消息的同时性,分别使用多线程,是的可以同时接收,发送消息。
服务器端完整代码如下:
//实现client发送账号、密码,server给出匹配成功or失败,成功则接收客户端的消息,失败则关闭客户端
//增加了界面友好型,以及多个用户
//封装版
/*** 1.创建ServerSocket(int port)对象* 2.在Socket上监听客户端的连接请求* 3.阻塞、等待连接的建立* 4.接收并处理请求信息* 5.将处理结果返回给客户端* 6.关闭流和Socket对象* @author dell**/
public class TestChatServer03 {public static void main(String[] args) throws IOException {System.out.println("-----Server-----");//1.创建ServerSocket(int port)对象ServerSocket server=new ServerSocket(6666);Socket client=null;
// ArrayList<OutputStream> list=new ArrayList<>();CopyOnWriteArrayList<OutputStream> list=new CopyOnWriteArrayList<>();boolean flag=true;while(flag) {//2.在Socket上监听客户端的连接请求client=server.accept();//3.阻塞、等待连接的建立 System.out.println("建立好了一次连接"); //这样写必须等第一个客户端建立好了连接,发送了账号、密码,才能接收其他的客户端//使用线程的原因,是因为可以不用等待线程体中的代码运行完,再次接收客户端的请求new Thread(new Channel(client,list)).start();}server.close(); }static class Channel implements Runnable{private Socket client;private DataInputStream is;private DataOutputStream os;String trueName="lkj";String truePassWord="123";String name="";String passWord="";CopyOnWriteArrayList<OutputStream> list;public Channel(Socket client,CopyOnWriteArrayList<OutputStream> list) {this.list=list;this.client = client;try {//从流中读取消息,【接收客户端的消息】this.is =new DataInputStream(client.getInputStream());//写到到消息到流中,【发送消息到客户端】this.os =new DataOutputStream(client.getOutputStream());} catch (IOException e) {e.printStackTrace();};}@Overridepublic void run() {//4.接收并处理请求信息 //先接受账号,密码信息,匹配成功,读取client的其它信息,失败,则关闭clientString str="";try {//从流中读取消息,【接收客户端的消息】str=is.readUTF();//分割str得到name,passWordthis.splitStr(str);//匹配成功if((trueName.equals(name)&&truePassWord.equals(passWord))||(name.equals("aaa")&&passWord.equals("123"))||(name.equals("bbb")&&passWord.equals("123"))){os.writeUTF("欢迎回来主人!!!");System.out.println("客户端登入成功!!!");list.add(client.getOutputStream());for(OutputStream oos:list) {if(oos!=client.getOutputStream()) {this.writeU(name+"进入了群聊!!!", oos);}}//从client读取的内容,反馈输出,通信this.comWithClient();list.remove(client.getOutputStream());}else {//匹配失败os.writeUTF("用户名或密码不正确");System.out.println("客户端登入失败,可能是用户名或密码不正确");}} catch (IOException e) {e.printStackTrace();}//6.关闭流和Socket对象System.out.println("接收完毕!!!");
// this.free();}private String readU() {try {return is.readUTF();} catch (IOException e) {e.printStackTrace();}return null;}private void writeU(String str,OutputStream os) {try {new DataOutputStream(os).writeUTF(str);} catch (IOException e) {e.printStackTrace();}}//分割str得到name,passWordprivate void splitStr(String str) {if(str.indexOf("&")!=-1) {//str.contains("&")String[] s=str.split("&");for(String s2:s) {if(s2.split("=")[0].equals("name")) {name=s2.split("=")[1];}else if(s2.split("=")[0].equals("passWord")) {passWord=s2.split("=")[1];}}}}//从client读取的内容,反馈输出private void comWithClient() throws IOException {//读取客户端的内容,并输出至客户端String str="";while(!str.equals("exit")) {//因为客户端使用的是BufferedReader 丢弃了\r\n,方便,可以直接判断,否则是,length()-2str=this.readU();//5.将处理结果返回给客户端if(list.size()<=1) {this.writeU("当前群聊只有你自己,"+name+"对自己说:-->"+str,client.getOutputStream());}else {for(OutputStream oos:list) {if(oos!=client.getOutputStream()) {this.writeU(name+"对大家说:"+str, oos);}}}}}private void free() {try {if(null!=os) {os.close(); }} catch (IOException e) {e.printStackTrace();}try {if(null!=is) {is.close();}} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}try {if(null!=client) {client.close(); }} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}}}
客户端完整代码如下:
//实现client发送账号、密码,server给出匹配成功or失败,成功则接收客户端的消息,失败则关闭客户端
//增加了界面友好型,以及多个用户/*** 1.创建Socket(String host,int port)对象* 2.向服务器发送连接请求* 3.向服务器发送服务请求* 4.接收服务结果* 5.关闭流和Socket对象* @author dell**/
public class TestChatClient03 {public static void main(String[] args) throws IOException {System.out.println("-----Client-----");//1.创建Socket(String host,int port)对象//2.向服务器发送连接请求Socket client=new Socket("localhost",6666);//3.向服务器发送服务请求//从输入流中读取消息,发送到流【服务器】中BufferedReader is=new BufferedReader(new InputStreamReader(System.in));DataOutputStream os=new DataOutputStream(client.getOutputStream());System.out.print("输入账户名:");String name=is.readLine();System.out.print("输入密码:");String passWord=is.readLine();os.writeUTF("name="+name+"&"+"passWord="+passWord);os.flush();//从流中读取消息【从服务器读取】DataInputStream dis=new DataInputStream(client.getInputStream());String str=dis.readUTF();System.out.println("客户端反馈的内容为-->"+str);if(str.equals("欢迎回来主人!!!")) {System.out.println("开始发送消息啦!!!");new Thread(new Sended(client)).start();new Thread(new Getted(client)).start();}else {System.out.println("登入失败,自动关闭客户端");}//5.关闭流和Socket对象
// client.close();}static class Sended implements Runnable{private Socket client;private BufferedReader is;private DataOutputStream os;public Sended(Socket client) {super();this.client = client;try {is=new BufferedReader(new InputStreamReader(System.in));os=new DataOutputStream(client.getOutputStream());} catch (IOException e) {e.printStackTrace();}}public void run() {String str="";while(!str.equals("exit")) {try {str=is.readLine();os.writeUTF(str);} catch (IOException e) {e.printStackTrace();}}
// this.free();}private void free() {try {if(null!=os) {os.close(); }} catch (IOException e) {e.printStackTrace();}try {if(null!=is) {is.close();}} catch (IOException e) {e.printStackTrace();}
// try {
// if(null!=client) {
// client.close();
// }
// }catch(IOException e) {
// e.printStackTrace();
// }}}static class Getted implements Runnable{private Socket client;private DataInputStream is;public Getted(Socket client) {super();this.client = client;try {is=new DataInputStream(client.getInputStream());} catch (IOException e) {e.printStackTrace();}}public void run() {String str="";while(!str.equals("exit")) {try {str=is.readUTF();System.out.println(str);} catch (IOException e) {e.printStackTrace();}}
// this.free();}private void free() {try {if(null!=is) {is.close();}} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}}
}