1、获取访问者的IP
public String getIp(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.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(); if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)){ try { ip= InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } } return ip }
/** * 获取访问者IP * 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。 * 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割), * 如果还不存在则调用Request .getRemoteAddr()。 * * @param request * @return */ public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("X-Real-IP"); if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { return ip; } ip = request.getHeader("X-Forwarded-For"); if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { // 多次反向代理后会有多个IP值,第一个为真实IP。 int index = ip.indexOf(','); if (index != -1) { return ip.substring(0, index); } else { return ip; } } else { return request.getRemoteAddr(); } }
2、Calendar
public class TestCalendar { @Test public void test(){ try { Calendar calendar = new GregorianCalendar();//子类实例化 //获取年、月、日、时、分、秒、毫秒 System.out.println("年: "+calendar.get(Calendar.YEAR)); System.out.println("月 "+(calendar.get(Calendar.MONTH)+1)); System.out.println("日: "+calendar.get(Calendar.DAY_OF_MONTH)); System.out.println("时: "+calendar.get(Calendar.HOUR_OF_DAY)); System.out.println("分: "+calendar.get(Calendar.MINUTE)); System.out.println("秒: "+calendar.get(Calendar.SECOND)); System.out.println("毫秒 "+calendar.get(Calendar.MILLISECOND)); // 当前月第一天、最后一天 int currYear = calendar.get(Calendar.YEAR); int currMonth = calendar.get(Calendar.MONTH) + 1; System.out.print(currYear + "-" + currMonth); SimpleDateFormat datef = new SimpleDateFormat("yyyy-MM-dd"); calendar.set(Calendar.DAY_OF_MONTH, 1); Date beginTime = calendar.getTime(); String sTime = datef.format(beginTime) + " 00:00:00"; calendar.set(Calendar.DATE, 1); calendar.roll(Calendar.DATE, -1); Date endTime = calendar.getTime(); String eTime = datef.format(endTime) + " 23:59:59"; System.out.println("第一天"+sTime+"最后一天"+eTime); Calendar cal = Calendar.getInstance(); //指定年月的的第一天、最后一天 int year = 2015; int moth = 3; cal.set(Calendar.YEAR,year); cal.set(Calendar.MONTH, moth-1); //当前月的最后一天 cal.set( Calendar.DATE, 1 ); cal.roll(Calendar.DATE, - 1 ); Date endTime2=cal.getTime(); String endTimeStr=datef.format(endTime2)+" 23:59:59"; //当前月的第一天 cal.set(GregorianCalendar.DAY_OF_MONTH, 1); Date beginTime2=cal.getTime(); String beginTimeStr=datef.format(beginTime2)+" 00:00:00"; System.out.println("指定年月的的第一天"+endTimeStr+"最后一天"+beginTimeStr); //当前时间的前一天 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd:HH"); String tmStr = "2015-5-18:00"; Date d = sdf2.parse(tmStr); System.out.println(d); Calendar now = Calendar.getInstance(); now.setTime(d); now.set(Calendar.HOUR, now.get(Calendar.HOUR) -1); System.out.println(sdf2.format(now.getTime())); //最近N天 SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); cal.add(Calendar.DATE,-7); System.out.println("最近7天"+df2.format(cal.getTime())); Calendar ca2 =Calendar.getInstance(); //最近N个月 ca2.add(Calendar.MONTH,-1);//最近一个月 System.out.println("最近一个月"+df2.format(ca2.getTime())); Calendar ca3 =Calendar.getInstance(); //最近N个年 ca3.add(Calendar.YEAR,-1);//最近一年 System.out.println("最近一年"+df2.format(ca3.getTime())); } catch (Exception e) { e.printStackTrace(); } } }3、判断socket是否已经断开
于是,下面一段代码就可以判断远端是否断开了连接:
try{ socket.sendUrgentData(0xFF); }catch(Exception ex){ reconnect(); }
用ping实现
package com.csdn.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class test { static BufferedReader bufferedReader; public static void main(String[] args) throws IOException { try { Process process = Runtime.getRuntime().exec("ping 192.168.1.104");//判断是否连接的IP; bufferedReader = new BufferedReader(new InputStreamReader(process .getInputStream())); String connectionStr = ""; while ((connectionStr = bufferedReader.readLine()) != null) { System.out.println(connectionStr); } } catch (IOException e) { e.printStackTrace(); } finally { bufferedReader.close(); } } }
ping的方法有个严重的BUG,就是你只能判断对方是否连接网络,而不能判断客户端是否开启,
在写聊天室时经常要注意客户端异常退出的问题(比如客户直接调用任务管理器结束程序进程),
其实在通过socket.getoutstream和socket.getinputstream流对客户端发送、接受信息时如果socket没连接上是会抛出异常的,这也就是为什么Java会要求网络编程都要写在try里面,所以只要在catch里面写入客户端退出的处理就行了,没必要专门去想什么方法
socket长连接:
package com.yihongyu.exec.modules.crx.service.impl; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.util.Iterator; import java.util.Properties; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.yihongyu.exec.modules.crx.manager.CrxNotificationManager; import com.yihongyu.exec.modules.crx.service.CrxNotificationService; import com.yihongyu.exec.modules.crx.service.CrxSocketClientService; @Service public class CrxSocketClientServiceImpl implements CrxSocketClientService { private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10); @Autowired private CrxNotificationService crxNotificationService; private Socket socket; private Properties props = new Properties(); private String host; private String portStr; /** 初始化Socket连接信息 */ @Override @PostConstruct public void init() { try { props.load(new FileInputStream("conf/notifications/crx.properties")); host = props.getProperty("crx.host", "192.168.1.225"); portStr = props.getProperty("crx.port", "8222"); Integer port = Integer.parseInt(portStr); connect(host, port); } catch (FileNotFoundException e) { LoggerFactory.getLogger(getClass()).error("无法找到Crx服务器配置文件,请检查是否存在文件:conf/notifications/crx.properties!"); } catch (IOException e) { LoggerFactory.getLogger(getClass()).error("装载Crx服务器配置文件失败:conf/notifications/crx.properties!", e); } } /** 创建Socket连接 */ @Override public Boolean connect(String host, int port) { try { destroy(); this.socket = new Socket(host, port); if (!isOrNotServerClose()) { System.out.println("----------------Connection Crx socket success!----------------"); } else { System.out.println("----------------Connection Crx socket fail!----------------"); LoggerFactory.getLogger(getClass()).error("Connection Crx socket fail!"); } socket.setSoTimeout(60000); socket.setKeepAlive(true); isServerClose(); return socket.isConnected(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); return false; } } /** 检测服务端Socket是否断开 */ @Override public void isServerClose() { executor.schedule(new Runnable() { @Override public void run() { try { System.out.println("=================sendUrgentData================="); socket.sendUrgentData(0XFF); isServerClose(); } catch (IOException e) {// 出现异常,服务端主动断开 destroy(); isServerClose(); LoggerFactory.getLogger(getClass()).error("Crx Server Exception Close!"); LoggerFactory.getLogger(getClass()).error("重新向服务端发起连接"); reConnect();// 重新向服务端发起连接 e.printStackTrace(); } } }, 10000, TimeUnit.MILLISECONDS); } /** 重新创建连接 */ @Override public boolean reConnect() { try { Integer port = Integer.parseInt(portStr); this.socket = new Socket(host, port); if (!isOrNotServerClose()) { System.out.println("----------------Connection Crx socket success!----------------"); } else { System.out.println("----------------Connection Crx socket fail!----------------"); LoggerFactory.getLogger(getClass()).error("Connection Crx socket fail!"); } socket.setSoTimeout(60000); socket.setKeepAlive(true); return true; } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); return false; } } @Override public Boolean isOrNotServerClose() { try { socket.sendUrgentData(0XFF); return false; } catch (IOException e) {// 出现异常,服务端主动断开 LoggerFactory.getLogger(getClass()).error("Crx Server Exception Close!"); e.printStackTrace(); return true; } } /** 向Crx服务端发送信息 */ @Override public String process(String contentXml) { try { System.out.println("Send CrxNotification Xml: " + contentXml); if (contentXml != null && contentXml.length() > 0) { OutputStream out = this.socket.getOutputStream(); out.write(contentXml.getBytes("GBK")); } } catch (IOException e) { e.printStackTrace(); } return null; } /** 获取Crx服务端返回的信息 */ @Override public String getCrxMsg() throws UnsupportedEncodingException, IOException { // 服务端返回的消息状态: 0--发送成功, 1--发送失改, 2--超时 String crxServerMsg = null; InputStream in = socket.getInputStream(); if (in.available() > 0) { byte[] buff = new byte[in.available()]; in.read(buff); crxServerMsg = new String(buff); } return crxServerMsg; } /** 关闭socket */ @Override public void destroy() { try { if (this.socket != null) { this.socket.close(); } } catch (IOException e) { e.printStackTrace(); } } }
4、UDP丢包及无序问题
在项目中做了个验证程序.
发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象.
纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了.
有没有成熟的解决方案来解决这个问题.
我用过sleep(1),暂时解决这个问题,但是这不是根本解决办法,如果数据量大而多,网络情况不太好的话,还是有可能丢失.
你试着用阻塞模式吧...
select...我开始的时候好像也遇到过..不过改为阻塞模式后就没这个问题了...
采用回包机制,每个发包必须收到回包后再发下一个
UDP丢包是正常现象,因为它是不安全的。
丢包的原因我想并不是“服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了”,而是服务器端的socket接收缓存满了(udp没有流量控制,因此发送速度比接收速度快,很容易出现这种情况),然后系统就会将后来收到的包丢弃。你可以尝试用setsockopt()将接收缓存(SO_RCVBUF)加大看看能不能解决问题。
服务端采用多线程pthread接包处理
UDP是无连接的,面向消息的数据传输协议,与TCP相比,有两个致命的缺点,一是数据包容易丢失,二是数据包无序。
要实现文件的可靠传输,就必须在上层对数据丢包和乱序作特殊处理,必须要有要有丢包重发机制和超时机制。
常见的可靠传输算法有模拟TCP协议,重发请求(ARQ)协议,它又可分为连续ARQ协议、选择重发ARQ协议、滑动窗口协议等等。
如果只是小规模程序,也可以自己实现丢包处理,原理基本上就是给文件分块,每个数据包的头部添加一个唯一标识序号的ID值,当接收的包头部ID不是期望中的ID号,则判定丢包,将丢包ID发回服务端,服务器端接到丢包响应则重发丢失的数据包。
模拟TCP协议也相对简单,3次握手的思想对丢包处理很有帮助。
udp是不安全的,如果不加任何控制,不仅会丢失包,还可能收到包的顺序和发送包的顺序不一样。这个必须在自己程序中加以控制才行。
收到包后,要返回一个应答,如果发送端在一定时间内没有收到应答,则要重发。
UDP本来存在丢包现象,现在的解决方案暂时考虑双方增加握手.
这样做起来,就是UDP协议里面加上了TCP的实现方法.
程序中采用的是pthread处理,丢包率时大时小,不稳定可靠
我感觉原因可能有两个,一个是客户端发送过快,网络状况不好或者超过服务器接收速度,就会丢包。
第二个原因是服务器收到包后,还要进行一些处理,而这段时间客户端发送的包没有去收,造成丢包。
解决方法:
方法一:客户端降低发送速度,可以等待回包,或者加一些延迟。
方法二:服务器部分单独开一个线程,去接收UDP数据,存放在一个缓冲区中,又另外的线程去处理收到的数据,尽量减少因为处理数据延时造成的丢包。
有两种方法解决楼主的问题:
方法一:重新设计一下协议,增加接收确认超时重发。(推荐)
方法二:在接收方,将通信和处理分开,增加个应用缓冲区;如果有需要增加接收socket的系统缓冲区。(本方法不能从根本解决问题,只能改善)
网络丢包,是再正常不过的了。
既然用UDP,就要接受丢包的现实,否则请用TCP。
如果必须使用UDP,而且丢包又是不能接受的,只好自己实现确认和重传,说白了,就是自己实现TCP(当然是部分和有限的简单实现)。
UDP是而向无连接的,用户在实施UDP编程时,必须制定上层的协议,包括流控制,简单的超时和重传机制,如果不要求是实时数据,我想TCP可能会更适合你!
5、java读取clob字段的几种方法
第一种 Clob clob = rs.getClob("remark");//java.sql.Clob String detailinfo = ""; if(clob != null){ detailinfo = clob.getSubString((long)1,(int)clob.length()); } 第二种: Clob clob = rs.getClob("remark");//java.sql.Clob int i = 0; if(clob != null){ InputStream input = clob.getAsciiStream(); int len = (int)clob.length(); byte by[] = new byte[len]; while(-1 != (i = input.read(by, 0, by.length))){ input.read(by, 0, i); } detailinfo = new String(by, "utf-8"); } 第三种: Clob clob = rs.getClob("remark");//java.sql.Clob String value=""; String line=""; if(clob!=null){ Reader reader=((oracle.sql.CLOB)clob).getCharacterStream(); BufferedReader br=new BufferedReader(reader); while((line=br.readLine())!=null){ value += line + "\r\n"; } } 第一种方法代码量少,且能避免中文乱码问题;第二种方法与第一种方法效率差不多,也是常使用的一种方法;第三种方法效率极低,如果数据比较大的话建议不要使用。
6、Url请求方式中文乱码问题解决
jsp中post方式请求一般不会乱码,如果乱码加上这句: 解决办法一 request.setCharacterEncoding("utf-8"); 而get方式请求,若url含非西欧编码必然会乱码,处理方式: request.setCharacterEncoding("utf-8"); //将请求参数使用ISO-8859-1分解成字节数组,再将字节数组解码成字符串 String name = new String(request.getParamet("name").getBytes("ISO-8859-1"),"utf-8"); 解决办法二 java.net.URLEncoder.encode()传送字符编码 面贴一下解决这个问题参考的文章: 使用java.net.URLEncoder.encode()可以对要传递的中文进行编码 a.在传参数之前先把参数进行转码:java.net.URLEncoder.encode(param); 取值时用语句java.net.URLDecoder.decode(param);再转回中文 b.在你的Tomcat目录-->conf目录-->server.xml里找出这段: <Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443(www.111cn.net)" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" <!--在里边加上这个参数--> URIEncoding="gb2312" />
相关推荐
Java 中操作 Oracle 的 CLOB 字段精解 Java 中操作 Oracle 的 CLOB 字段是一种常见的操作,在实际开发中,我们经常需要在 Oracle 数据库中存储和读取大型文本数据,这时就需要使用 CLOB(Character Large OBject)...
在数据库.link连接远程数据库时,经常会遇到无法使用CLOB字段的问题,这是因为CLOB字段在远程数据库中的处理方式与本地数据库不同所导致的。下面将讨论解决dblink_clob字段异常的解决方案。 什么是dblink? DBLink...
在Java中处理Oracle的CLOB字段,首先需要导入相关的Java SQL包以及Oracle JDBC驱动特有的类。这些包括`java.sql.*`,`java.io.*`,以及`oracle.jdbc.driver.*`和`oracle.sql.*`。这一步是建立与Oracle数据库连接的...
本教程将介绍如何使用Java来读取和写入Oracle数据库中的CLOB字段。 首先,我们需要引入相关的Java和Oracle JDBC驱动库。在上述代码中,我们看到`import oracle.jdbc.driver.OracleDriver;`,这表示我们将使用Oracle...
在Java编程中,JDBC(Java Database Connectivity)是用于与各种数据库进行交互的一套标准API。当我们在处理大型文本数据时,例如XML文档、长篇文章或者大段代码,数据库通常会提供CLOB(Character Large Object)...
### 数据库读取CLOB字段 #### 概述 在Oracle数据库中,CLOB(Character Large Object)是一种用于存储大量文本数据的数据类型。CLOB能够容纳4GB的文本信息,适用于存储如文章、报告或者XML文档等大型文本数据。...
### 读取Oracle数据库中CLOB字段的值 在处理Oracle数据库时,经常会遇到需要读取CLOB(Character Large Object)类型字段的情况。CLOB主要用于存储大量的文本数据,如文章、文档等内容。由于CLOB类型的数据量可能...
修改clob blob 字段 修改clob blob 字段 修改clob blob 字段
在Oracle数据库中,CLOB(Character Large Object)字段类型用于存储大量的文本数据,如XML文档、长篇文章或者大量字符数据。然而,当你尝试向CLOB字段插入数据时,如果超过了Oracle规定的最大限制,就会遇到“ORA-...
JDBC读写Oracle的CLOB字段
### ORACLE中CLOB字段转String类型 在Oracle数据库中,`CLOB`(Character Large Object)是一种用于存储大量文本数据的数据类型。由于其能够存储非常大的文本块(最大可达4GB),因此常被用于存储文章、报告或任何...
java读取oracle数据库中clob字段 把oracle数据库中字段类型为clob的字段值以字符串的形式读取出来
Oracle CLOB 行字段全文检索实现方法 Oracle 数据库中,CLOB 行字段是一种常用的数据类型,用于存储大文本数据。然而,在 Oracle8i 版本之前,对大字段 CLOB 仍然不支持在 where 子句直接的 Like 操作。这使得...
CLOB操作与BLOB操作类似,但是在获取java.sql.Clob对象后需要强制转换为oracle.sql.CLOB对象,以便使用getCharacterOutputStream()方法将数据写入CLOB字段。 三、出库操作 出库操作可以使用ResultSet.getBlob()或...
在描述中提到的“Oracle导出Clob,Blob等大字段工具”就是为了解决这个问题而设计的,它是一个自编写的实用程序,方便用户导出和管理Oracle数据库中的大对象数据。 Oracle数据库中的Clob类型用于存储大量的文本数据...
Mybatis 处理 CLOB、BLOB 类型数据 MyBatis 处理 CLOB、BLOB 类型数据是指在使用 MyBatis 框架时,如何正确地处理大字段类型的数据。CLOB(Character Large OBject)和 BLOB(Binary Large OBject)都是大字段类型...
Hibernate存储Clob字段的方式总结涉及了在Java开发中使用Hibernate操作大型文本字段Clob的操作方法。本文主要介绍了两种操作Clob字段的方法,一种是将Clob字段直接映射为String类型,另一种是使用Clob类型进行处理。...
在 Java 中,通过使用 oracle.sql.CLOB 类来处理 CLOB 类型字段的存储和读取。 在 Java 中,连接 Oracle 数据库需要使用 Oracle 的 JDBC 驱动程序。首先,需要使用 Class.forName() 方法加载驱动程序,然后使用 ...