• 我高中接触计算机,那时候还是AppleII,绿色显示器的,我因为入学学习成绩一般,没有列入学习计算机的队伍。我是凭个人关系,我室友的叔叔,是机房负责人,呵呵, 挤进去的。高三,剩下的只有2人了。 另一个
    论坛和QQ里经常有人问到类似的问题。我根据我的个人情况,大致整理一下自己的心得。  

    1 爱好。
      这个是动力,如果你不爱Java,不爱计算机,而是喜爱游戏,娱乐或者其他的,你不适合做程序员。
      我高中接触计算机,那时候还是AppleII,绿色显示器的,我因为入学学习成绩一般,没有列入学习计算机的队伍。我是凭个人关系,我室友的叔叔,是机房负责人,呵呵, 挤进去的。高三,剩下的只有2人了。 另一个考到了四川的一个科技大学,我忘了,是很牛气的学校。
      大学,我没有考上计算机系,但是我基本上和计算机系的人混得最熟,他们的机房我去的非常多。晚上经常不回宿舍,吃方便面,小浣熊干脆面, 几个朋友一起弄东西,主要是汇编和C语言,还有玩三国2和大富翁2的游戏。
      毕业,在化工厂混了5年,实在没兴趣,转行到IT了,还算顺利。 

    请注意:我是27岁改行进入IT的,那些总说该怎么样怎么样的人,应该知道怎么做了吧! 现在开始还不晚!

      如果你能在电脑前,一坐就是4-5个小时,你能为了学习而阅读英文的资料,那么你至少对编程是热爱的,具备了程序员的潜质。

    2 学会取舍,用到什么就学什么
      编程路上知识点甚多,你能掌握的永远是很少的一部分,新的技术不断出现,你难道能跟上? 相反,编程思想确是相对稳定的。
      对于新手,到书店找一本入门的书,用最快的速度读一遍,不要超过3天。 记住,你不需要理解,因为你理解不了,你只需要对那些东西有个大概的意识,噢噢噢,好像有那么几页有这个东西,能达到这个效果就非常不错了。 千万不要一开始从第一章就仔细的看,那没用。
      看完之后,找你最感兴趣的部分看,如果看不懂哪些内容,就去翻其他部分,然后马上返回。这部分看懂后,马上开机训练。
      对于已经有经验的人,新知识你可以看看他的介绍,Release Note 或则一些评论性文章,然后看看自己手头有没有合适的工作可以用到,如果用不到,停止继续研究,如果能用到,则深入的看一遍他的文档,方法和前面一样,不能太细。 看完后,如果能运用,则开机尝试,并仔细的阅读即将使用到的部分。

    有网友问:怎么选入门的书?
    我回答
    书店,搜索,  
    Java 入门 

    你能看到一大堆,随便一本,看!记得不要买!!! 

    入门书差不多!不要太细的看。 

    换一本,加深印象 

    回家,电脑上实践,或者找电子版的书! 

    转天再去。


    3 技术服从于业务
      技术是用来解决问题的,而不是用来炫耀的。当技术与业务有矛盾时,业务永远在第一位。
      不要和业务人员过度的讨论(注意不是争吵)技术如何如何? 有什么技术难点无法满足业务需求之类的。
      技术人员可以作出自认为很好的东西,但不一定能卖的出去。世界已经不再是【好酒不怕巷子深】的年代了。除非你真的有强的专利技术。

    4 认识自己
      不是每个人都能做到CTO,CEO的,金字塔的顶部的空间是很少的。由于家庭环境和个人性格不同,而高层领导的强项并不是在技术,而是在沟通和管理。也许你不服,也许你不甘心,但事实如此,只有付出更多的努力,才有可能往塔尖靠近,注意是有可能,不是一定。

    5 学会总结
      知识如果不用,就会被逐渐淡忘,当你需要的时候,如何能用最短的时间回复呢?那就是记笔记。 blog很好,写在笔记本上也行,写在一个word文件里面也好。 总之,以你能很快的能找到为准。

    6 身体是本钱
      不多说了,大家都清楚。但会不自觉的违反这一条。呵呵!

    7 正确理解学习过程
      初学时,就是死记硬背,你只需要知道应该怎么样就可以了。
      有一定经验后,你就需要知道,还能怎么样?
      熟悉后,你应该知道为什么要这样?如果不这样会怎么样
      精通,这个东西适合吗?如何选择呢?

      初学:动手
      掌握:动手又动脑
      熟悉:动脑又动手
      精通:动脑

    8  学会正确的查找问题答案的方法
        一搜二问三看看 【阿敏总司令】

    • 先搜搜,坚信 你绝对不是第一个遇到这个问题的人
      先到 google/baidu 搜索 选好关键字
    • 到论坛或者群里面发问
    • 学会平时积累,到处看看,经常有意外收获。 n月前的难题可以轻松解决。
    • 你的问题一定要有经过你思考了的。不要直接要全部代码和答案的那种。 至少我鄙视他们。没有人会花费那么多时间提供一个整套方案,就算付费的也得谈谈价钱,不合适的也不做。
      比如:
      我要做一个学生学籍管理系统,请提供思路和详细的解释,最好有源代码,100分送上
      请问如何学好Java啊?我要学啥啊?
      老师让明天交作业,哪位大哥给一份答案啊?
      领导让做个库存管理软件 让我写需要 应该怎么写呢? 大家帮帮我啊?

    9 增加你的实战经验
      你可以没做过,但一定要认真思考过
      你可能没做过什么像样的项目,至少你自己这么认为。其实不然,你做过的的项目虽然看上去小,但你可以遵循这样的目标来完善
    • 去目标用户那里调研,了解真实的需求,不要停留在想象程度
    • 单机版改成多用户版
    • C/S版增加B/S版,反之亦然
    • 使用正式的数据库,而不是Access
    • 完善你的程序,直到有人愿意出钱买你的程序(1元也算),因为这代表着他是一个真正能用的,能满足实际需求的程序了
    • 去看看别人的项目代码,好多开源的项目。看看人家是怎么解决同样的问题的。


    10 先学做人,后学做事
      大家放眼望去会发现:大凡成功者,在谈到成功时,很少谈“做事”,而都在讲“做人”。因为不会做人,就不会做事,就会走上无为的一生,或走上大起大落坎坷艰难的不归之路

    一网友抱怨,技术总监用老掉牙的技术和思想指挥一个上千万的项目,他想按照规范来做,结果和总监发生争吵和冲突。 最后被总监提出,你辞职吧。

    下面是我回复的内容,有点刻薄。

    奉劝你一句,你有什么资格和你的直属最高领导吵架????? 

    1 意见不和,可以私下提,不要当面顶撞,这无济于事。如果我是老板,我也开除你。 
    2 技术要服从于业务,如果你总是对的,你为何不自己做老板?你能拉来几千万的项目? 
    3 既然大家谈不拢,和平离开就可以了。我估你你们没有个人恩怨。不过目前好像有了。

    我以前也和你一样,自己认为都是对的,可实际呢? 没有我们,地球照样转,人家几千万的项目照样做。 

    当你做老板,你的手下人每天都顶撞你时,你也会这么做。 历史上刚直不阿的人,大多是悲惨的下场。 

    社会就是这样,理想和现实是有差距的。  

    #### 针对第10条的部分内容,我已经在反馈里给了解释############################
    解决问题的方法有好多,最好不要走那个最不好走的路。肚量再大的领导,也会有冲动的时候。
    如果平时多注意沟通,如网友所说,能和领导经常喝喝酒,吃吃烧烤,目的能达到,还增进感情

    from:http://www.java2000.net/viewthread.jsp?tid=1691







    <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
    展开全文
  • 怎么用Java写一个客户端程序。 开局还是我们熟悉的Main函数: 我们选用的客户端技术是 javaFX . 不同于以前的swing , awt , 是新一代的桌面客户端编码方式 JavaFX是由甲骨文公司推出的一系列的产品和技术,该产品于...

    写了这么多期的代码,
    一直都是在控制台里面,
    都没有像别的软件那样,
    可以有一个桌面客户端的形式,
    可以用鼠标点,
    用键盘输入。
    下面我们就来看看,
    怎么用Java写一个客户端程序。

    开局还是我们熟悉的Main函数:

    我们选用的客户端技术是 javaFX .
    不同于以前的swing , awt ,
    是新一代的桌面客户端编码方式

    JavaFX是由甲骨文公司推出的一系列的产品和技术,该产品于2007年5月在JavaOne大会上首次对外公布。JavaFX技术主要应用于创建Rich Internet application(RIAs)。当前的JavaFX包括JavaFX脚本和JavaFX Mobile(一种运营于移动设备的操作系统),今后JavaFX将包括更多的产品。
    JavaFX脚本的前身是一个由Chris Oliver开发的一个叫做F3的项目。
    Swing是一个为Java设计的GUI工具包。Swing是Java基础类的一部分。Swing包括了图形用户界面(GUI)组件如:文本框,文本域,按钮,分隔窗格和表。
    Swing提供许多比AWT更好的屏幕显示元素。它们用纯Java写成,所以同Java本身一样可以跨平台运行,这一点不像AWT。它们是JFC的一部分。它们支持可更换的面板和主题(各种操作系统默认的特有主题),然而不是真的使用原生平台提供的设备,而是仅仅在表面上模仿它们。这意味着你可以在任意平台上使用Java支持的任意面板。轻量级组件的缺点则是执行速度较慢,优点就是可以在所有平台上采用统一的行为。

    代码如下:
    public class Main extends Application{

    @Override
    public void start(Stage primaryStage) throws Exception{
        //设置主窗体
        StackPane root = new StackPane();
        //标题
        primaryStage.setTitle("java-util公众号:java技术大本营");
        //大小
        primaryStage.setScene(new Scene(root, 500, 300));
        //开始显示
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
    

    }
    分割线 箭头 动态
    效果如下:

    这样一个桌面客户端程序的底板就出来了,我们可以在上面添加按钮,添加文本框等等我们需要的东西。

    代码地址:
    https://github.com/weixiaodexiaoxiaodao/java-utils

    谁说程序员木讷的,这里有用代码写出的三行情诗,了解一下~

    饭后一笑|那些年被误会的程序员们~

    工作后才发现…

    动态黑色音符
    小编整理了一些java进阶学习资料和面试题,需要资料的请加JAVA高阶学习Q群:664389243 这是小编创建的java高阶学习交流群,加群一起交流学习深造。群里也有小编整理的2019年最新最全的java高阶学习资料!

    展开全文
  • Java获取客户端IP

    2016-06-20 17:01:47
    转载地址:Java获取客户端IP 在开发工作中,我们常常需要获取客户端的IP。一般获取客户端的IP地址的方法是:request.getRemoteAddr();但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。原因...

    转载地址:Java获取客户端IP
    这里虽然是转载的博文,在看博文之前先说明一下,如果你使用的是公司的内网访问,那么对外的出口可能只有一个或者几个,那么客户端的IP就有可能两个人获取的同样的IP!
    在开发工作中,我们常常需要获取客户端的IP。一般获取客户端的IP地址的方法是:request.getRemoteAddr();但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。

    原因:由于在客户端和服务之间增加了中间代理,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。

    现在图示代理上网和IP的关系:
    这里写图片描述
    第二种情况:通过代理服务器如:Nginx,Squid等一层代理或多层代理上网,如下图:
    这里写图片描述
    需要注意的是X-Forwarded-For和X-Real-IP都不是http的正式协议头,而是squid等反向代理软件最早引入的,之所以resin能拿到,是因为NGINX里一般缺省都会这么配置转发的http请求:

    location / {
    
             proxy_pass       http://yourdomain.com;
    
             proxy_set_header   Host             $host;
    
             proxy_set_header   X-Real-IP        $remote_addr;
    
             proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    
             }

    从X-Forwarded-For的定义来看,ips[0]才是原始客户端ip,如果这个都不是,那拿第二个就更不靠谱了,我们平时检验的时候,可能是直接在内网挂代理去访问的,跟外面网友访问经过的网络路径不一样,后面不停添加的是经过的每一层代理ip才对,下面举例说明;

    request.getRemoteAddr() 192.168.239.196

    request.getHeader(“X-Forwarded-For”) 58.63.227.162, 192.168.237.178, 192.168.238.218

    request.getHeader(“X-Real-IP”) 192.168.238.218

    所以访问的流程应该是这样,客户端58.63.227.162发出请求,经过192.168.237.178, 192.168.238.218两层转发,到了192.168.239.196这台NGINX上,NGINX就把X-Real-IP头设成了自己看到的remote_addr,也就是直接发给到他的192.168.238.218,这时候resin收到这个包,对resin来说直接发给他的remote_addr就是NGINX的ip,也就是192.168.239.196,那么resin里面的request.getRemoteAddr()就是192.168.239.196,那么在resin里拿最原始的ip逻辑(也就是拿能够知道的最外层的ip)应该是这样:

            如果XFF不为空,拿XFF的左边第一个
    
            如果XFF为空,拿XRI
    
            如果XRI为空,只能拿request.getRemoteAddr(),也就是只能拿到最直接发给他的机器ip了,
    

    其他都不可考究,参考代码如下:

    第一种代码:

    /**
          * 从Request对象中获得客户端IP,处理了HTTP代理服务器和Nginx的反向代理截取了ip
          * @param request
          * @return ip
          */
        public static String getLocalIp(HttpServletRequest request) {
            String remoteAddr = request.getRemoteAddr();
            String forwarded = request.getHeader("X-Forwarded-For");
            String realIp = request.getHeader("X-Real-IP");
    
            String ip = null;
            if (realIp == null) {
                if (forwarded == null) {
                    ip = remoteAddr;
                } else {
                    ip = remoteAddr + "/" + forwarded.split(",")[0];
                }
            } else {
                if (realIp.equals(forwarded)) {
                    ip = realIp;
                } else {
                    if(forwarded != null){
                        forwarded = forwarded.split(",")[0];
                    }
                    ip = realIp + "/" + forwarded;
                }
            }
            return ip;
        }

    第二种代码:

    public static String getIp(HttpServletRequest request) {
            String remoteAddr = request.getRemoteAddr();
            String forwarded = request.getHeader("X-Forwarded-For");
            String realIp = request.getHeader("X-Real-IP");
    
            String ip = null;
            if (realIp == null) {
                if (forwarded == null) {
                    ip = remoteAddr;
                } else {
                    ip = remoteAddr + "/" + forwarded;
                }
            } else {
                if (realIp.equals(forwarded)) {
                    ip = realIp;
                } else {
                    ip = realIp + "/" + forwarded.replaceAll(", " + realIp, "");
                }
            }
            return ip;
        }

    第三种代码:

    public static String getIp2(HttpServletRequest request) {
               String ip = request.getHeader("X-Forwarded-For");
               if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
                   //多次反向代理后会有多个ip值,第一个ip才是真实ip
                   int index = ip.indexOf(",");
                   if(index != -1){
                       return ip.substring(0,index);
                   }else{
                       return ip;
                   }
               }
               ip = request.getHeader("X-Real-IP");
               if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
                   return ip;
               }
               return request.getRemoteAddr();
           }

    第三种是最合适的,最清晰理解的!

    附两个方法:也是从其他地方看到的,记录下来,方便以后学习!

    /**
     * 通过HttpServletRequest返回IP地址
     * @param request HttpServletRequest
     * @return ip String
     * @throws Exception
     */
    public String getIpAddr(HttpServletRequest request) throws Exception {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    
    
     /**
     * 通过IP地址获取MAC地址
     * @param ip String,127.0.0.1格式
     * @return mac String
     * @throws Exception
     */
    public String getMACAddress(String ip) throws Exception {
        String line = "";
        String macAddress = "";
        final String MAC_ADDRESS_PREFIX = "MAC Address = ";
        final String LOOPBACK_ADDRESS = "127.0.0.1";
        //如果为127.0.0.1,则获取本地MAC地址。
        if (LOOPBACK_ADDRESS.equals(ip)) {
            InetAddress inetAddress = InetAddress.getLocalHost();
            //貌似此方法需要JDK1.6。
            byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
            //下面代码是把mac地址拼装成String
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                //mac[i] & 0xFF 是为了把byte转化为正整数
                String s = Integer.toHexString(mac[i] & 0xFF);
                sb.append(s.length() == 1 ? 0 + s : s);
            }
            //把字符串所有小写字母改为大写成为正规的mac地址并返回
            macAddress = sb.toString().trim().toUpperCase();
            return macAddress;
        }
        //获取非本地IP的MAC地址
        try {
            Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
            InputStreamReader isr = new InputStreamReader(p.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            while ((line = br.readLine()) != null) {
                if (line != null) {
                    int index = line.indexOf(MAC_ADDRESS_PREFIX);
                    if (index != -1) {
                        macAddress = line.substring(index + MAC_ADDRESS_PREFIX.length()).trim().toUpperCase();
                    }
                }
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace(System.out);
        }
        return macAddress;
    }
    展开全文
  • Java通信之客户端的创建以及客户端和服务器的简单交互   一、客户端的创建 现在所使用的是windows自带telnet客户端,并且只能发送英文,今天我们将自己创建客户端,并让客户端和服务器进行简答的交互,跟前面的...

    Java通信之客户端的创建以及客户端和服务器的简单交互

     

    一、客户端的创建

    现在所使用的是windows自带telnet客户端,并且只能发送英文,今天我们将自己创建客户端,并让客户端和服务器进行简答的交互,跟前面的压缩和解压缩一样,客户端和服务器不是一个工程,是两个工程;分开写

      客户端创建的实现步骤:

    先创建Socket对象,并给定ip和端口就可以完成和服务器的连接

    Socket  client = new Socket(ip地址,端口号);

     

    二、同步消息和异步消息(与客户端和服务器的交互有关)

    同步消息:消息发送方发送完消息后,一定要等对方反馈消息后,才能有后续消息发送动作(登录,注册是否成功)

    异步消息:消息发送发只管发消息,不需要的到对方的反馈(消息的发送和接收)

     

    三、客户端和服务器的简单交互

    拿我们前面简单的多人聊天室来说,首先,客户端的连接服务器;一旦连接成功,服务器会发送消息给客户端,所连接成功,并要求客户端输入用户名和密码进行登录;当输入用户名和密码以后,服务器端会进行校验,返回给客户端一个信息,看是否登录成功;如果登录成功,则可以多人聊天了,否则登录失败,要求重新登录;前面这一部分登录都是属于同步消息,一定要等到对方反馈消息后,才能有后续等到消息发送动作,一旦登录成功,后面服务器需要一直接受来自客户端的消息,并把消息转发出去,而客户端则需要一直处于接受消息的状态,发送消息和接收消息是一步消息,不需要等待反馈消息;

     

    四、源代码

    服务器端代码:

     

    
     
    package com.huaxin.server;
    
    
    import java.io.IOException;
    
    import java.net.ServerSocket;
    
    import java.net.Socket;
    
    import java.util.ArrayList;
    
    
    public class Myserver {
    
    
    public static ArrayList<ServerThread>list =new ArrayList<ServerThread>();
    
    public void initServer() {
    
    
    try {
    
    //创建服务器对象,并指定端口号
    
    ServerSocket server = new ServerSocket(9090);
    
    System.out.println("服务器已经建立......");
    
    //不断获取客户端的连接
    
    while(true){
    
    Socket socket =server.accept();
    
    System.out.println("客户端连接进来了......");
    
    //当有客户端连接进来以后,开启一个线程,用来处理该客户端的逻辑,
    
    ServerThread st = new ServerThread(socket);
    
    st.start();
    
    //添加该客户端到容器中
    
    list.add(st);
    
    }
    
    } catch (Exception e) {
    
    e.printStackTrace();
    
    }
    
    
    }
    
    
    }

     

     

     

    package com.huaxin.server;
    
    
    import java.io.IOException;
    
    import java.io.InputStream;
    
    import java.io.OutputStream;
    
    import java.net.Socket;
    
    
    public class ServerThread extends Thread {
    
    
    public Socket socket;
    
    public InputStream ins;
    
    public OutputStream ous;
    
    
    public ServerThread(Socket socket) {
    
    this.socket = socket;
    
    }
    
    
    public void run() {
    
    try {
    
    // 获取输入输出流
    
    ins = socket.getInputStream();
    
    ous = socket.getOutputStream();
    
    // 发送消息给客户端
    
    String msg = "welcome to zhou's server !";
    
    sendMsg(ous, msg);
    
    // 发送要求登录信息给客户端
    
    String userinfo = "please input your name:";
    
    sendMsg(ous, userinfo);
    
    // 获取客户端输入的用户名
    
    String userName = readMsg(ins);
    
    // 发送要求密码信息给客户端
    
    String pwd = "please input your password:";
    
    sendMsg(ous, pwd);
    
    // 获取客户端输入的密码
    
    String pass = readMsg(ins);
    
    // 登录验证
    
    boolean falg = loginCheck(userName, pass);
    
    // 校验不通过时,循环校验
    
    while (!falg) {
    
    msg="no";
    
    sendMsg(ous, msg);
    
    msg = "Fail to connect server......";
    
    sendMsg(ous, msg);
    
    msg = "please check your name and password and login again.....";
    
    sendMsg(ous, msg);
    
    msg = "please input your name:";
    
    sendMsg(ous, msg);
    
    // 获取客户端输入的用户名
    
    userName = readMsg(ins);
    
    // 发送要求密码信息给客户端
    
    msg = "please input your password:";
    
    sendMsg(ous, msg);
    
    // 获取客户端输入的密码
    
    pass = readMsg(ins);
    
    falg = loginCheck(userName, pass);
    
    }
    
    
    //发送登录成功的结果给客户端
    
    msg="ok";
    
    sendMsg(ous, msg);
    
    // 校验成功后:开始聊天
    
    msg = "successful connected..... you can chat with your friends now ......";
    
    sendMsg(ous, msg);
    
    // 聊天处理逻辑
    
    //读取客户端发来的消息
    
    msg=readMsg(ins);
    
    System.out.println("客户端已经接到消息:"+msg);
    
    //输入bye结束聊天
    
    while(!"bye".equals(msg)){
    
    //给容器中的每个对象转发消息
    
    for (int i = 0; i <Myserver.list.size(); i++) {
    
    ServerThread st =Myserver.list.get(i);
    
    //不该自己转发消息
    
    if(st!=this){
    
    System.out.println("转发消息......");
    
    sendMsg(st.ous, userName+" is say:"+msg);
    
    System.out.println("转发消息成功......");
    
    }
    
    }
    
    //等待读取下一次的消息
    
    msg=readMsg(ins);
    
    }
    
    
    } catch (Exception e) {
    
    System.out.println("客户端不正常关闭......");
    
    // e.printStackTrace();
    
    }
    
    //有异常后统一将流关闭
    
    try {
    
    ins.close();
    
    ous.close();
    
    socket.close();
    
    //将当前已经关闭的客户端从容器中移除
    
    Myserver.list.remove(this);
    
    } catch (IOException e) {
    
    // TODO Auto-generated catch block
    
    e.printStackTrace();
    
    }
    
    }
    
    
    // 校验客户端输入的账号和密码的函数,由于没有数据库,暂时写死了
    
    public boolean loginCheck(String name, String pwd) {
    
    if (name.equals("zhou") && pwd.equals("zhou") || name.equals("user") && pwd.equals("pwd")
    
    || name.equals("huaxinjiaoyu") && pwd.equals("huaxinjiaoyu")) {
    
    
    return true;
    
    }
    
    return false;
    
    }
    
    
    // 发送消息的函数
    
    public void sendMsg(OutputStream os, String s) throws IOException {
    
    // 向客户端输出信息
    
    byte[] bytes = s.getBytes();
    
    os.write(bytes);
    
    os.write(13);
    
    os.write(10);
    
    os.flush();
    
    
    }
    
    
    // 读取客户端输入数据的函数
    
    public String readMsg(InputStream ins) throws Exception {
    
    // 读取客户端的信息
    
    int value = ins.read();
    
    // 读取整行 读取到回车(13)换行(10)时停止读
    
    String str = "";
    
    while (value != 10) {
    
    // 点击关闭客户端时会返回-1值
    
    if (value == -1) {
    
    throw new Exception();
    
    }
    
    str = str + ((char) value);
    
    value = ins.read();
    
    }
    
    str = str.trim();
    
    return str;
    
    }
    
    
    }


    服务器端启动类:

     

     

    
     
    package com.huaxin.server;
    
    
    public class Test {
    
    
    public static void main(String[] args) {
    
    Myserver ms = new Myserver();
    
    ms.initServer();
    
    }
    
    
    }


     

     

    客户端代码:

     

    
     
    package com.huaxin.client;
    
    
    import java.io.InputStream;
    
    import java.io.OutputStream;
    
    import java.net.Socket;
    
    import java.util.Scanner;
    
    
    public class Myclient {
    
    public static void main(String[] args) {
    
    Myclient mc = new Myclient();
    
    mc.initClient();
    
    }
    
    
    public void initClient() {
    
    try {
    
    // 创建客户端对象
    
    Socket client = new Socket("localhost", 9090);
    
    // 获取客户端的输入输出流
    
    final InputStream ins = client.getInputStream();
    
    final OutputStream ous = client.getOutputStream();
    
    // 先接收服务器发送的欢迎词
    
    String msg = readMsg(ins);
    
    System.out.println(msg);
    
    // 接收服务端发送过来输入用户名的请求
    
    String requestName = readMsg(ins);
    
    System.out.println(requestName);
    
    // 获取用户名信息,从控制台
    
    final Scanner scanner = new Scanner(System.in);
    
    String username = scanner.nextLine();
    
    // 发送用户名
    
    sendMsg(ous, username + "\r\n");
    
    // 读取密码请求
    
    String requestPwd = readMsg(ins);
    
    System.out.println(requestPwd);
    
    // 从控制台扫描密码
    
    String pwd = scanner.nextLine();
    
    // 把密码发送给服务器
    
    sendMsg(ous, pwd + "\r\n");
    
    // 获取验证结果
    
    String result = readMsg(ins);
    
    //如果登录失败,则接受服务器端发过来的提示消息
    
    while(!result.equals("ok")){
    
    //接收"Fail to connect server......"
    
    String message=readMsg(ins);
    
    System.out.println(message);
    
    //接收"please check your name and password and login again....."
    
    message=readMsg(ins);
    
    System.out.println(message);
    
    //接收 "please input your name:""
    
    message=readMsg(ins);
    
    System.out.println(message);
    
    //重新发送用户名给服务器
    
    username = scanner.nextLine();
    
    // 发送用户名
    
    sendMsg(ous, username + "\r\n");
    
    //接受密码请求"please input your password:"
    
    message=readMsg(ins);
    
    System.out.println(message);
    
    //发送密码给服务器
    
    pwd = scanner.nextLine();
    
    // 发送用户名
    
    sendMsg(ous, pwd + "\r\n");
    
    //接收服务器返的信息
    
    result = readMsg(ins);
    
    }
    
    //如果登录成功,则可以开始聊天了
    
    if (result.equals("ok")) {
    
    // System.out.println("登陆成功");
    
    // 发送消息线程
    
    new Thread() {
    
    public void run() {
    
    try {
    
    while (true) {
    
    // 从控制台扫描一行数据
    
    String message = scanner.nextLine();
    
    sendMsg(ous, message + "\r\n");
    
    }
    
    } catch (Exception e) {
    
    e.printStackTrace();
    
    }
    
    
    };
    
    }.start();
    
    
    //读取消息线程
    
    new Thread() {
    
    public void run() {
    
    try {
    
    while (true) {
    
    String message = readMsg(ins);
    
    System.out.println(message);
    
    }
    
    } catch (Exception e) {
    
    e.printStackTrace();
    
    }
    
    };
    
    }.start();
    
    } else {
    
    System.out.println("登陆失败");
    
    }
    
    } catch (Exception e) {
    
    e.printStackTrace();
    
    }
    
    }
    
    
    public String readMsg(InputStream ins) throws Exception {
    
    int value = ins.read();
    
    String str = "";
    
    while (value != 10) {
    
    // 代表客户单不正常关闭
    
    if (value == -1) {
    
    throw new Exception();
    
    }
    
    str = str + (char) value;
    
    value = ins.read();
    
    }
    
    str = str.trim();
    
    return str;
    
    }
    
    
    // 发送消息的函数
    
    public void sendMsg(OutputStream ous, String str) throws Exception {
    
    byte[] bytes = str.getBytes();
    
    ous.write(bytes);
    
    ous.flush();
    
    }
    
    }
    
    


     

     

    五、运行结果截图:

    先开启服务器:

     

    错误登录测试:

     

    重新开启服务器,并开启三个客户端(启动三次客户端的代码,输入不同的用户名和密码即可)

     

     

    客户端1、

     

    客户端2

     

     

    客户端3

     

     

    六、总结

     

    1、客户端的创建其实还是挺简单的,就两行代码

    2、客户端和服务器端的交互看似很复杂,其实,如果服务器那端早已经在前面写好了,客户端这边只要只要根据服务器那边来写代码就好了;需要注意的是客户端和服务器的读消息和发送消息的两个函数功能不要写错了;如果这里没问题,我们只需要看服务器那边怎么写的代码,客户单照着写就好了,比如,但客户端连接服务器后,服务器那边首先会发送一条欢迎的消息给客户端,所以,客户端建立好并连接服务器以后,那么,第一步就是接收服务器发送过来的欢迎词;接下来第二步,服务器会发送用户名请求给客户端,那么客户端首先要做的是接收这条消息,然后输入用户名,并将输入的用户名发送给服务器,这里用到了Scanner类,不懂的请自行百度!然后,就是这么一步一步按部就班的来;服务器那边怎么写,客户端这边就怎么接,就这么简单!

    3、经验分享:遇到问题,不要慌;出错真的是好事,以前会害怕出错,现在真的是一点都不害怕了;调试bug的能力才是衡量一个程序员高低好坏的标准,所以,遇到错误不要怕!要勇于直面bug;最常用的一招抓bug的方法就是打印一条语句,看这条语句是否执行了,没有执行,说明这里没有执行到,在我的程序中,会看到很多被注释的system.out.println语句,那就是调试bug用的!

    共勉!

     

    最近整理出了有关大数据,微服务,分布式,Java,Python,Web前端,产品运营,交互等1.7G的学习资料,有视频教程,源码,课件,软件工具,面试题等等,这里将珍藏多年的资源免费分享给各位小伙伴们。

    领取方式:https://blog.csdn.net/qq_42914528/article/details/81777449                                      

                                                             

    欢迎大家关注我的公众号:

    里面会分享很多JAVA技术、新知识、新技术、面试宝典等。
    有让技术爱好者(程序猿)得到很大提升的文章资料。

    还在犹豫什么,赶紧关注一波,微信搜索公众号:程序员的成长之路。或者扫描下方二维码进行关注。

                                                                         

                                                                           欢迎关注公众号,和我一起成长!

    展开全文
  • 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。 如果使用了反向代理软件,将...

    image

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。

    如果使用了反向代理软件,将http://192.168.1.110:2046/的URL反向代理为http://www.abc.com/的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或192.168.1.110,而并不是客户端的真实IP。

    经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。

    当我们访问http://www.abc.com/index.jsp/时,其实并不是我们浏览器真正访问到了服务器上的index.jsp文件,而是先由代理服务器去访问http://192.168.1.110:2046/index.jsp,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问index.jsp的,所以index.jsp中通过request.getRemoteAddr()的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。

    外界流传的JAVA/PHP服务器端获取客户端IP都是这么取的:

    伪代码:

    1)ip = request.getHeader(“X-FORWARDED-FOR “)

    2)如果该值为空或数组长度为0或等于”unknown”,那么:
    ip = request.getHeader(“Proxy-Client-IP”)

    3)如果该值为空或数组长度为0或等于”unknown”,那么:
    ip = request.getHeader(“WL-Proxy-Client-IP”)

    4)如果该值为空或数组长度为0或等于”unknown”,那么:
    ip = request.getHeader(“HTTP_CLIENT_IP”)

    5)如果该值为空或数组长度为0或等于”unknown”,那么:
    ip = request.getHeader(“X-Real-IP”)

    6)如果该值为空或数组长度为0或等于”unknown”,那么:
    ip = request.getRemoteAddr ()

    先说说这些请求头的意思

    • X-Forwarded-For

    这是一个 Squid 开发的字段,只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。

    格式为X-Forwarded-For:client1,proxy1,proxy2,一般情况下,第一个ip为客户端真实ip,后面的为经过的代理服务器ip。现在大部分的代理都会加上这个请求头。

    • Proxy-Client-IP/WL- Proxy-Client-IP

    这个一般是经过apache http服务器的请求才会有,用apache http做代理时一般会加上Proxy-Client-IP请求头,而WL-Proxy-Client-IP是他的weblogic插件加上的头。

    • HTTP_CLIENT_IP

    有些代理服务器会加上此请求头。

    • X-Real-IP
      nginx代理一般会加上此请求头。

    下面是一个参考获取客户端IP地址的方法:

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.contains(",")) {
            return ip.split(",")[0];
        } else {
            return ip;
        }
    }

    如果使用的是Druid连接池,可以参考使用:com.alibaba.druid.util.DruidWebUtils#getRemoteAddr方法,但这个是经过多级代理的IP地址,需要自己处理下获取第一个。

    有几点要注意

    1. 这些请求头都不是http协议里的标准请求头,也就是说这个是各个代理服务器自己规定的表示客户端地址的请求头。如果哪天有一个代理服务器软件用oooo-client-ip这个请求头代表客户端请求,那上面的代码就不行了。

    2. 这些请求头不是代理服务器一定会带上的,网络上的很多匿名代理就没有这些请求头,所以获取到的客户端ip不一定是真实的客户端ip。代理服务器一般都可以自定义请求头设置。

    3. 即使请求经过的代理都会按自己的规范附上代理请求头,上面的代码也不能确保获得的一定是客户端ip。不同的网络架构,判断请求头的顺序是不一样的。

    4. 最重要的一点,请求头都是可以伪造的。如果一些对客户端校验较严格的应用(比如投票)要获取客户端ip,应该直接使用ip=request.getRemoteAddr(),虽然获取到的可能是代理的ip而不是客户端的ip,但这个获取到的ip基本上是不可能伪造的,也就杜绝了刷票的可能。(有分析说arp欺骗+syn有可能伪造此ip,如果真的可以,这是所有基于TCP协议都存在的漏洞),这个ip是tcp连接里的ip。

    参考
    http://blog.csdn.net/sgx425021234/article/details/19043459
    http://blog.csdn.net/fengwind1/article/details/51992528

    推荐阅读


    资料:成为架构师的十阶段学习资料!

    教程:史上最强 Spring Boot & Cloud 教程汇总

    工具:推荐一款在线创作流程图、思维导图软件

    扫描关注我们的微信公众号,回复 “666” 可获取一套Java并发编程高清视频教程。

    image

    展开全文
  • 我想问的是,客户端软件一般用什么数据库,java的derby? 我的jdk是1.8我看里面有一个db文件夹,是不是直接用这个db就行 请大神指点~~~ ------------------------分割线----------------------------- 可能我的...
  • java写的ftp客户端源码

    2020-06-24 14:37:45
    java写的ftp客户端源码,很久之前了,用的是apache的net包里面的ftp功能,然后自己做了一些swing的操作界面,添加了上传下载速度进度,和图片预览功能。源码里面有Test类,因为是为了学习swing mvc才打算做一个的,...
  • ZooKeeper Java 客户端连接 文章代码是跟着zk学习视频敲的。 import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache....
  • JDBC客户端操作--启动Hive远程服务  hive --service hiveserver   Hive的JDBC客户端操作 打开Eclipse,新建一个JAVA项目,新建一个lib目录,将hive安装目录下的jdbc.jar文件拷贝进来,加载进path路径; 新建...
  • Java应用程序在桌面客户端上部署有很多办法。Oracle JDK的官方文档里其实包含了对各种部署方法的讲解:Java Platform, Standard Edition Deployment Guide 其中一个有趣的选项是:Self-Contained Application ...
  • zkclient是zookeeper的Java客户端。它让Zookeeper API 使用起来更简单;它非常方便订阅各种事件并自动重新绑定事件(会话建立、节点修改、节点删除、子节点变更等);它提供了session过期自动重连等机制。今天我们...
  • 引进 maven 依赖 <!--https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper--> <dependency> <groupId>org.apache.zookeeper</groupId> <...zooke...
  • 大家都知道,zookeeper作为一个分布式服务框架,用来解决分布式数据不一致的问题,今天来看看的提供的java语言的API,下面是zookeeper 3.4.1的文档地址,百度的api...  看上去还是比较简洁的,那么我们先看看连接...
  • 最近在学习CXF的使用,成功发布CXF使用过后,想利用wsdl2java来生产客户端程序,提示如下报错Missing argument: wsdlurl看到这个错,感觉是没有写wsdlurl导致,可是我确实写了如下wsdl2java -d ....
  • 这篇文章中,我们讲述一下用Java实现网络通信的的基本流程,这里讲述的是不基于任何框架的原生语言自带的写法。Java服务器端写法:程序入口代码如下:public static void main(String[] args) { try { // ① ...
  • JAVA开发人员出去面试,基本是必问Redis。redis分为客户端和服务端两个部分,这次就是通过手写一个Redis的客户端,让你掌握里面的知识。RESP协议RESP协议是Redis客户端和服务端之间的通讯协议,这是它的官方文档:...
  • Java小程序之客户端的UI实现以及客户端与服务器的UI交互(山寨QQ进行中......) 一、前言 通过前面的学习,我们已经能够自己创建客户端,不需要依赖系统自带的telnet客户端,但是,我们只能利用控制台和后台服务器...
  • 使用cdm根据WSDL网址生成java客户端代码 windows下使用cmd命令提示符生成java webservice客户端代码,可以使用命令提示符直接生成客户端代码,直接导入到项目中,只需配置jdk即可,在jdk的bin文件夹下,按Shift并...
  • 一句话来说,C++和Java 通过socket进行通信、数据传输,通过发送“字节流”即可。 字节对于C++和java来说是通用的,但是在传输数据有许多问题需要注意,我为了弄清楚这个过程,查了一些资料,做了一些总结整理。   ...
  • 前面我们介绍了通信技术的基础知识,今天我们尝试来用JAVA来创建一个简单的...建议大家在学习JAVA的通信之前先把JAVA中的文件的读取和输出先搞懂。(可以参考我的另一篇博客《JAVA文件读取和写入(内附简单的代...
1 2 3 4 5 ... 20
收藏数 218,706
精华内容 87,482