socket实现人多聊天与Java代码加载过程

第一部分是java代码加载过程

关于java代码加载过程,今天调试了阿里巴巴一份代码,如下:

/**
 * 加载方法不等于执行方法,初始化变量则会赋值
 *             类加载顺序应为 加载静态方法-初始化静态变量-执行静态代码块
 *             实例化时 先加载非静态方法-实例化非静态变量-执行构造代码块-执行构造函数
 * @author panteng
 *
 */
public class StaticTest {
    /**第一个加载*/
    public static int k = 0;
    /**第二个加载,因为是new一个实例,
     * 首先初始化j 打印出  1:j i=0 n=0
     * 执行构造块     打印出  2:构造快 i=1 n=1
     * 执行构造方法 打印出  3:t1 i=2 n=2
     * 实例化完成
     */
    public static StaticTest t1 = new StaticTest("t1");
    /**第三个加载 过程同上
     * 首先初始化j 打印出  4:j i=3 n=3
     * 执行构造块     打印出  5:构造快 i=4 n=4
     * 执行构造方法 打印出  6:t2 i=5 n=5
     */
    public static StaticTest t2 = new StaticTest("t2");
    /**第四个加载
     * 打印出  7:i i=6 n=6
     */
    public static int i = print("i");
    /**
     * 第五个加载
     */
    public static int n = 99;
    /**
     * 此变量在类加载的时候并不初始化,在实例化类的时候初始化
     */
    public int j = print("j");

    {
        print("构造快");
    }
    /**
     * 第六个加载 此时,n已经被初始化  所以打印出
     * 8:静态块 i=7 n=99
     */
    static{
        print("静态块");
    }
    //-----------以上属于类加载---------------------
    /**
     * 实例化过程:
     *         首先加载非静态方法集;
     *         初始化非静态变量:9:j i=8 n=100
     *         执行构造块:10:构造快 i=9 n=101
     *         执行构造方法:11:init i=10 n=102
     * 实例化完成
     */

    /**
     * 执行构造函数  实例化完成
     * @param str
     */
    public StaticTest(String str) {
        System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
        ++n;
        ++i;
    }
    /**
     * 这个应该是最先加载 但是,加载不等于执行
     * 因为如果不加载此函数,静态变量是无法初始化的
     * @param str
     * @return
     */
    public static int print(String str) {
        System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
        ++i;
        return ++n;
    }

    public static void main(String[] args) {
        StaticTest t = new StaticTest("init");
    }

}

    首先加载类,然后实例化:

          类加载过程:
                  首先加载所有的静态方法,但不执行;
                  然后按照静态变量的顺序开始初始化
                  静态变量初始化完毕后执行静态构造块(不执行构造块)
                  此时类加载完毕
          实例化过程:
                  加载非静态方法
                  初始化非静态变量
                  执行构造代码块
                  执行构造函数
                  此时实例化完毕

第二部分是socket实现多对多的群聊   代码部分跟昨天实现一对一的变化主要在服务器这端,在服务端使用List集合来保存一组socket,每当有一个客户端向服务端发送socket时,都会将这个socket加入到数组列表中,然后开启一个新的线程来为这个客户端群发消息。介于昨天使用BufferInputStream的readLine方法出现了换行问题,今天直接使用字节来传输消息,InputStream的方法read(byte[] b)方法可以将读到的数据传到字节数组中,并且返回字节数组的长度,int len = in.read(b),然后将字节数组转换成字符串,String str = new String(b,0,len);输出的时候也不一定使用PrintWriter方法,可以直接使用socket.getOutputStream()返回的OutputStream来发送数据,注意前者PrintWriter是使用print,后者OutputStream是使用write方法。e.g:    out.print(str);e.g:    out.write(str.getByte());传输方法跟昨天的有所不同,以及服务端的改动,我还是讲客户端和服务端的代码发一遍。客户端:
import java.net.*;
import java.io.*;
import java.util.Scanner;

public class Client {

    public static String sg ;//客户端用户名

    public Client() {
        try {

            Socket socket = new Socket("127.0.0.1", 4800);
            System.out.println("客户端已经开启----");
            System.out.println("请取您的用户名");
            Scanner scanner = new Scanner(System.in);
            sg=scanner.next();
            new Thread(new Output(socket)).start();
            new Thread(new Input(socket)).start();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    class Input implements Runnable {
        Socket socket;

        public Input(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            while (true) {
                try {
                    InputStream in = socket.getInputStream();
                    byte[] b = new byte[1024];
                    int len = in.read(b);

                    String str = new String(b, 0, len);
                    System.out.println(str);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

//输出信息到服务端
    class Output implements Runnable {
        Socket socket;

        public Output(Socket socket) {
            this.socket = socket;
        }

        public void run() {

            try {
                Scanner scanner = new Scanner(System.in);
                while(true) {
                    OutputStream out = socket.getOutputStream();
                    String str = sg+":"+scanner.next();
                    out.write(str.getBytes());
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new Client();
    }
}

  服务端代码:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {

    List<Socket> list = new ArrayList<Socket>();//将收到客户端的socket添加到数组列表

    public Server() {
        try {
            ServerSocket serverSocket = new ServerSocket(4800);
            System.out.println("服务端正在等待客户端请求......");

            while (true) {
                Socket socket = serverSocket.accept();
                new Thread(new Output(socket, list)).start();
                list.add(socket);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class Output implements Runnable {
        Socket socket;
        List<Socket> list;

        public Output(Socket socket, List<Socket> list) {
            this.socket = socket;
            this.list = list;
        }

        public void run() {
            try {
                while (true) {
                    InputStream in = socket.getInputStream();
                    byte[] b = new byte[1024];
                    int len = in.read(b);
                    String str = new String(b,0,len);
                    list.remove(socket);//每次群发消息不发给发送给服务器的一方客户端
                    for (Socket s:list){
                        OutputStream out = s.getOutputStream();
                        out.write(str.getBytes());
                    }
                    list.add(socket);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new Server();
    }
}

  以及今天无意间看到了关于线程的生命周期,权当复习一下:

总结     今天不是第一次使用socket了,遇到的问题不像昨天那么多,但是还是有很大一部分的问题,socket编程,关于TCP与UDP方面的通讯,现在还没有进行尝试,还有同一个局域网和不同网络方面的问题,学习还是需要一步步的来,不能一口吃撑胖子,今天也挺有收获的,了解了java加载类方面的知识,感觉在类实例化前,就先初始化了静态变量和方法,在以后的学习中可能会有用;实现了类似QQ群聊的功能,如果想多写点,我觉得既然有群聊,在群聊的基础上我还可以写个聊天室里一个用户对另一额用户的私聊,私聊方面现在思路基本就是,当客户端输入私聊+ID名,剩下的基本就是跟一对一一样的。
时间: 2024-11-05 22:07:09

socket实现人多聊天与Java代码加载过程的相关文章

Java web 加载过程

1.Web容器初始化过程 2.SpringMVC中web.xml配置 3.认识ServletContextListener 4.认识ContextLoaderListener 5.DispatcherServlet初始化(HttpServletBean ? FrameworkServlet ? DispatcherServlet) 6.ContextLoaderListener与DispatcherServlet关系 7.DispatcherServlet的设计 8.DispatcherServ

maven工程,java代码加载resources下面资源文件的路径

1 通过类加载器加载器, 1. URL resource = TestMain.class.getResource("/18500228040.txt"); File file = new File(resource.getFile()); String absolutePath = file.getAbsolutePath(); 这种方式得到的是绝对路径,window和linux会得到不同的结果,然后这些都会在编辑器里面运行程序的时候可以成功,但是一旦打成jar包的时候就会产生问题w

New UI-纯Java代码加载布局

New UI-纯Java代码加载布局  --转载请注明出处:coder-pig,欢迎转载,请勿用于商业用途! 小猪Android开发交流群已建立,欢迎大家加入,无论是新手,菜鸟,大神都可以,小猪一个人的 力量毕竟是有限的,写出来的东西肯定会有很多纰漏不足,欢迎大家指出,集思广益,让小猪的博文 更加的详尽,帮到更多的人,O(∩_∩)O谢谢! 小猪Android开发交流群:小猪Android开发交流群群号:421858269 新Android UI实例大全目录:http://blog.csdn.ne

Java基础6:代码块与代码加载顺序

Java基础6:代码块与代码加载顺序 代码块:用{}包围的代码 java中的代码块按其位置划分为四种: 局部代码块 位置:局部位置(方法内部) 作用:限定变量的生命周期,尽早释放,节约内存 调用:调用其所在的方法时执行 public class 局部代码块 {@Testpublic void test (){   B b = new B();   b.go();}}class B {   B(){}   public void go() {       //方法中的局部代码块,一般进行一次性地调

java虚拟机学习(四)类的加载过程

类从虚拟机内存加载到从内存卸载,经历的生命周期是:加载,验证,准备,解析,初始化,使用,卸载这几个阶段, 其中验证,解析,初始化被称为 连接过程(Linking). (打算这块和类加载原理后再看class文件结构那篇) 除了解析和使用,其他的过程基本顺序就是这样, 解析可以是在初始化完成之后,这是为了运行时动态绑定. 在虚拟机规范中定义了5中情况(有且只有)必须对类进行初始化(之前进行过,加载,验证,准备): 1.碰到new,getstatic,putstatic,invokestatic这4条

java如何加载本地的dll文件

首先,应当明确,dll有两类:(1)Java所依赖的dll和,(2)dll所依赖的dll.正是由于第(2)种dll的存在,才导致了java中加载dll的复杂性大大增加,许多说法都是这样的,但我实验的结果却表明似乎没有那么复杂,后面会予以详细阐述. 其次,Java中加载dll的方式也有两种:(1)通过调用System.loadLibrary(String filename)和,(2)通过调用System.load(String filename)方法.其底层都是通过使用ClassLoader中的l

java用户界面——加载图片 jpg GIF

java用户界面--加载图片 jpg GIF 代码如下: package day08; import java.awt.GridLayout; import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JLabel; public class Testdongyaidujiazai extends JFrame { private Icon image1 =

java动态加载指定的类或者jar包反射调用其方法

序言 有时候,项目中会用到java动态加载指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大降低,更加的模块化,代码利用率更高.模式中的代理模式就用到java的这一机制.下边就让我们通过代码来看看如何实现此功能. 代码详细 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoad

JAVA类的加载过程

周末闲来无事,做个小例子去看一下JAVA代码初始化的过程 JAVA代码初始化分为两个步骤:类初始化,对象初始化. 类初始化 1 类初始化是指类加载器将类加载到内存时,对类成员的初始化过程(其中包括static修饰的变量). 2 对于加载完的类,它的类变量都会赋一个默认值,即使你定义时就赋值了. 3 例如int类型就是0,引用类型就是null. 对象初始化 1 其实和类初始化差不多,但是他通过构造函数对对象进行了赋值 其实简单来说 类初始化做了2件事情:1 把所有属性全部赋值为0或者NULL,2