网络开发之聊天小代码

(1)目的:对网络开发的知识进行一定的实践,增强对网络开发的了解
(2)技术:1、简单的套接字的运用
2、简单的静态方法和变量的使用
3、基本的方法,如构造方法,hasmap的使用
4、多线程
(3)代码
1、这是我们的客户端

package online;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class client1 {
    public static void main(String [] args) throws IOException {
        //链接我们设置的服务端
        Socket socket = new Socket("10.129.0.123", 32917);
        //从终端输入我们的信息
        BufferedReader getline = new BufferedReader(new InputStreamReader(System.in));
        //创建一个字符串来接收我们的输入
        BufferedReader serint=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //接收从服务器回来的信息
        PrintStream output = new PrintStream(socket.getOutputStream());
        String mline;
        while(true) {
            String line = getline.readLine();
            mline=ruler.login + line + ruler.login;
            output.println(mline);
            String buget=serint.readLine();
            System.out.println(buget);
            if(buget.length()==4){
                System.out.println("登录成功!请记住你的昵称:"+line);break;
            }
            else {
                System.out.println("登入失败,此昵称已被他人使用");
                continue;
            }
        }//默认进去后首先选择的是输入名称
        player playtemp=new player(socket);//一个子线程,不断打印从服务器端打印出来的数据
        playtemp.start();//使这个线程进入就绪状态
        while((mline=getline.readLine())!=null){
            //output.println(ruler.person+mline+ruler.person);
            output.println(mline);
        }


    }
}
class client2{
    public static void main(String [] args) throws IOException {
        //链接我们设置的服务端
        Socket socket = new Socket("10.129.0.123", 32917);
        //从终端输入我们的信息
        BufferedReader getline = new BufferedReader(new InputStreamReader(System.in));
        //创建一个字符串来接收我们的输入
        BufferedReader serint=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //接收从服务器回来的信息
        PrintStream output = new PrintStream(socket.getOutputStream());
        String mline;
        while(true) {
            String line = getline.readLine();
            mline=ruler.login + line + ruler.login;
            output.println(mline);
            String buget=serint.readLine();
            System.out.println(buget);
            if(buget.length()==4){
                System.out.println("登录成功!请记住你的昵称:"+line);break;
            }
            else {
                System.out.println("登入失败,此昵称已被他人使用");
                continue;
            }
        }//默认进去后首先选择的是输入名称
        player playtemp=new player(socket);//一个子线程,不断打印从服务器端打印出来的数据
        playtemp.start();//使这个线程进入就绪状态
        while((mline=getline.readLine())!=null){
            output.println(mline);
        }

    }
}

2、我们的服务端,这里采用了多线程的使用

package online;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class serviver {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(32917);//设置这个类的端口
        //这里使用了对象方法的形式
        while (true) {//接收多个客户端
            Socket persocket = server.accept();//不停的接收客户端的输入
            playermannager player = new playermannager(persocket);
            player.start();
        }
    }
}

3、客户端子线程

package online;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class player extends Thread {
    Socket socket;
    public player(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        try {
            BufferedReader mget=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String mline;
            while((mline=mget.readLine())!=null){
                System.out.println(mline);
            }

        } catch (IOException e) {
        }
    }
}

4、服务端子线程

package online;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.HashMap;

public class playermannager extends Thread{
    public static HashMap box=new HashMap<>();
    //设置一个静态键值对管理我们的客户端口和套接字
   Socket socket;
   public playermannager(Socket socket){
       this.socket=socket;
   }
    @Override
    public void run() {
        BufferedReader mread;
        PrintStream moutput;
        try{
            mread=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            moutput=new PrintStream(socket.getOutputStream());
            System.out.println("链接成功");
            String mgetline;//创建一个字符串接收子类的信息
            while((mgetline = mread.readLine())!=null) {
                System.out.println(mgetline);
                if (mgetline.startsWith(ruler.login) && mgetline.endsWith(ruler.login)) {
                    String name = mgetline.substring(2, (mgetline.length() - 2));//条件语句,客户是否选择了登录
                        if (chooselogin(name)) {//引用了这个方法
                            playermannager.box.put(name, socket);//将这个套接字和名称一起放入我们之前准备的那个变量
                            System.out.println(playermannager.box.entrySet());
                            moutput.println("true");//传输给相应的子类
                        } else {
                            moutput.println("false");
                            continue;
                        }
                    }

                //创建一个私聊代码块
                if (mgetline.startsWith(ruler.person) && mgetline.endsWith(ruler.person)) {
                    //创建一个字符串接受这些信息
                    int len = mgetline.length() - 2;//一个整型记录其字符串的长度-2
                    String mgetline2 = mgetline.substring(2, len);//去调我们的前缀和后缀
                    String[] str = mgetline2.split(ruler.mytry);//按照我们规定的规则分割这个字符串
                    String mnametemp = str[0];//分割会形成两个数组
                    System.out.println(str[0]);
                    String connet = str[1];
                    Socket hesocket = playermannager.namesocket(mnametemp);//得到我们私聊对象的套接字
                    String myname=playermannager.socketname(socket);
                    PrintStream heout = new PrintStream(hesocket.getOutputStream());//输出
                    heout.println(myname + "对你说:" + connet);
                }
                if(mgetline.startsWith(ruler.persons) && mgetline.endsWith(ruler.persons)){
                    //还是创建一个字符串接受这些信息
                    String nametemp1=playermannager.socketname(socket);
                    for(String nametemp2:box.keySet()){
                        Socket sockettemp=box.get(nametemp2);
                        PrintStream outtemp=new PrintStream(sockettemp.getOutputStream());
                        outtemp.println(nametemp1+"群发说:"+mgetline);
                    }
                }
            }

        }catch (IOException e){

        }
    }

    public boolean chooselogin(String name){//一个对象方法,检查是否有重名现象
        for(String key:box.keySet()){
            if(key.equals(name)){
                return false;
            }
        }
        return true;
    }
    public static Socket namesocket(String name){//创建一个方法同过名字找到套接字
       return box.get(name);
    }
    public static String socketname(Socket socket){//创建一个方法同过套接字找到名字
        for(String key:box.keySet()){
            if(box.get(key)==socket)return key;
        }
        return null;
    }
}

5、一些常量,我放在一个类里了,果然,这里用线程要代码要好看点

package online;

public class ruler {
    public static final String login="a+";
    public static final String person="b+";
    public static final String persons="c+";
    public static final String mytry="&&";
}

感悟:网络开发的学习也有几天了,感觉这个阶段的代码学习就很神奇,有些错误错误总是在你觉得不可能出错时出现,留下我一脸的懵逼和被迫百度短则一两分钟多达一个多小时的无奈,关键是,还不一定搞的定。总的来说,这个阶段进度可以感觉到不是很快,不用很费力就能跟上。可是知识的学习,嗯,,,要多敲代码去检验呀,要多敲代码去检验呀,要多敲代码去检验呀!

你可能感兴趣的:(网络开发之聊天小代码)