在项目中调用SDK使用到数字的IP地址,IP地址由4个Byte组成一个4个字节的Int或UInt,如172.168.0.1 在字节中是 最高位是172 次高位是168 次低位是0 最低位是1,以二进制来表述就清楚了,把四个串联成的二进制数字计算出来就是一个UInt 或 Int的数字了。
在网上有解决代码,但觉得复杂,于是自己写了一个
/// <summary>
/// 将IPv4格式的字符串转换为int型表示
/// </summary>
/// <param name="strIPAddress">IPv4格式的字符</param>
/// <returns></returns>
public static int IPToNumber(string strIPAddress)
{
//将目标IP地址字符串strIPAddress转换为数字
string[] arrayIP = strIPAddress.Split('.');
int sip1 = Int32.Parse(arrayIP[0]);
int sip2 = Int32.Parse(arrayIP[1]);
int sip3 = Int32.Parse(arrayIP[2]);
int sip4 = Int32.Parse(arrayIP[3]);
int tmpIpNumber;
tmpIpNumber = (sip1 << 24) + (sip2 << 16) + (sip3 << 8) + sip4;
return tmpIpNumber;
}
/// <summary>
/// 将int型表示的IP还原成正常IPv4格式。
/// </summary>/// <param name="intIPAddress">
/// int型表示的IP
///</param>
/// <returns></returns>
public static string NumberToIP(int intIPAddress)
{
byte[] bs = BitConverter.GetBytes(intIPAddress);
return string.Format("{0}.{1}.{2}.{3}", bs[3], bs[2], bs[1], bs[0]);
}
public static string NumberToIP(uint intIPAddress)
{
byte[] bs = BitConverter.GetBytes(intIPAddress);
return string.Format("{0}.{1}.{2}.{3}", bs[3], bs[2], bs[1], bs[0]);
}
Java序列化的日期为是很标准,XStream中转换为标准的做法
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class DateConverter implements Converter {
private Locale locale;
public DateConverter(Locale locale) {
super();
this.locale = locale;
}
@Override
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context) {
Date date = (Date) value;
DateFormat formatter = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS");
// DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
// this.locale);
// 在这写输出的格式
writer.setValue(formatter.format(date));
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
GregorianCalendar calendar = new GregorianCalendar();
DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
this.locale);
try {
calendar.setTime(formatter.parse(reader.getValue()));
} catch (ParseException e) {
throw new ConversionException(e.getMessage(), e);
}
return calendar;
}
@Override
public boolean canConvert(Class clazz) {
// return Calendar.class.isAssignableFrom(clazz);
return Date.class.isAssignableFrom(clazz);
}
}
去掉Java的包名等
package com.anson.ws;
//import java.io.ByteArrayOutputStream;
import java.io.ByteArrayOutputStream;
import java.util.Locale;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
* @author jeo 08/12/29
*/
public class MQObjectToXMLUtil {
private static XStream sxstream;
static {
sxstream = new XStream(new DomDriver());
// 把MQ所用到的类的完全限定名,改为类名
sxstream.alias("Person", Person.class);
sxstream.alias("Book", Book.class);
//加入日期转换器
DateConverter converter = new DateConverter(Locale.CHINESE);
sxstream.registerConverter(converter);
}
/**
* 把java的可序列化的对象转换为XML格式的字符串
*
* @param obj
* 要序列化的可序列化的对象
*/
public static String objectXmlEncoder(Object obj) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
// XMLEncoder encoder = new XMLEncoder(bout);
String xml = null;
try {
// 对象序列化输出到字节流
// encoder.writeObject(obj);
// encoder.flush();
// 关闭序列化工具
// encoder.close();
// 由字节流中取得XML格式字符串
sxstream.toXML(obj, bout);
xml = new String(bout.toByteArray(), "utf-8");
// 关闭字节流
// bout.close();
} catch (Exception e) {
e.printStackTrace();
}
return xml;
}
}
曾经做好几个项目,由于考虑不同的平台,所以基本上都是基于Webservice(SOAP协议)来实现,服务器一般是使用Java来实现。本文只要说明C#的Webservice代理的使用及代理代码的生成。
由于项目算是比较大的,服务接口比较多,所以Webservice发布层都是有多个Url的,这种情况使用VS提供的WSDL生成工具好像就出现问题了,实体类代码和通信类(操作方法)代码都是放到一个文件里面了,如果Webservice发布时没有手动指定命名空间时,还会涉及到命名空间的问题,即实体类的属性完全相同,也会报命名空间的错误。所以在调用方,出现了同一实体,多处命名的问题。还有命名规范问题,如果发布方没有指定发布时的名称(如:实体中的属性,类名等),Java的Webservice发布工具默认是小写的,所以和C#通常为大写的做法不符,影响可读性。
具体做法:把WSDL生成的代理类的有关的实体手动分离出来,并把每个实体类的有关的命名空间注释去。(如果是同一个团队开发,可以按照指定的要求一起遵守,但如果是不同公司,一般来说都是调用方自己想办法解决了),把所有实体类放到同一个程序集里(有很多相同的可以保留一份),这样,我们基本上可以做实体做了统一管理,基本上可以使整个程序运行正常了。
维护成本:这些手动的工作的维护成本是相当大的,只要服务器每更改一次实体和操作方法(指要通过Webservice发布的方法),调用方必须得同步更新代理的代码,又得重新手动分离实体等,这种手动工作,往往带有很多隐性的错误,导致调试的时间增长,稳定度降低。
为了解决以上问题,本人牺牲了个人的休息时间,基于WSDL.exe上写了一个C#代理生成工具《Webservice代理生成工具》,从生成到代码导出,不需要更改一点代码,特别是在项目开发的初期,带来的效率和速度是不可比拟的。
本工具的功能有:
代理类相关功能:
1、可以对多个项目的Webservice代理生成进行管理;
2、对同一个项目的生成代理的多个Uri进行管理,最近使用的排在最前面,可以保留最近50个Uri及用户对每个Uri所使用的配置选项;
3、允许对代理进行重命名、指定代理的命名空间,更改代理的所指向的Url(此Url为运行时所要访问的地址,一般是在配置里,这里可以是配置实体的代码等。);
4、允许增加代理所需要引入的分离的实体的命名空间或配置访问等所需要的命名空间等。
5、生成的代理类类名首字母大写;
6、指定代理的导出的文件路径。
实体类相关功能:
1、可以选择要分离出的实体;只要是根据 "class" 来判断,有部分代码会对delegate所需要相关的内容都生成一个class,所以该选项得人为去指定,但系统会记录每次用户的指定,再次生成时会自动加载前一次的指定;
2、允许增加实体所需要的相关的命名空间;
3、指定实体所在的命名空间;
4、指定实体的类名前缀或后缀,如“Ety”等;
5、允许对WSDL中定义的类进行首字母大写;
6、允许对实体中的属性的首字母大写;
7、注释实体序列化时使用的命名空间;
8、时间的特别处理属性设置为真(该属性是WSDL.exe自动增加上去的,可能是为处理SOAP对不同时候格式的处理),如果不设置为真,调用方的时间字段是传送不到服务器端的。
9、设置导出的实体类的路径(一个实体一个.cs文件);
导出选项:
1、选择需要导出的文件;
工具图片:


限制部分功能版下载:/Files/Yjianyong/WebServiceProxyBuilder.rar
需要无限制版请联系QQ:179781134 加友时在备注说明,否则拒绝!
本工具属个人版权,和公司没有任何关系。
在很多操作中,都会使用到异步线程,具体怎样使用在这不说了,网上有很好的说明;本人通过Delegate.BeginInvoke实现异步调用,完成后对UI控件进行设值等,还有System.Timers.Timer都一样,使用的是线程池的线程。
在异步线程的执行方法中,如果直接使用Control.Invoke转到当前的工作线程,然后设置UI控件的值,完成后继续执行异步线程未完成的代码,不知道是异步线程没有被及时回收,还是别的原因,UI的句柄(可能是一个指针引用),在任务管理器中不断增加。应该是没有回收完成的异步线程的原因。如果使用Timer的Elapsed事件,好像是没有减少的,可能是Timer为全局性的吧,不去考究了。如果是使用new MethodInvoker().BeginInvoke的调用,过一段时间,句柄会减少(回收了)。
具体的解决办法:使用Control.BeginInvoke方法(如果需要同步控件及返回值的不能用些方法),Control.BeginInvoke的线程和上异步线程成了并行执行。是没有任何关系的两个线程了,测试表明,句柄没有增加,至于内存增加,是回收机制还没有执行所致(Event引起的内存泄露不能算,要处理),