如何检查端口占用情况

最近在给学生们做Demo的时候,遇到了一个端口占用的问题……既然知道问题的所在,就要开始尝试解决问题,检查出到底是哪个程序在使用这个端口,然后干掉它……

再Windows下,加入我的端口 3318被占用了,那么在cmd里执行

netstat -aon|findstr “3318”

得到结果如下

TCP    127.0.0.1:3318     127.0.0.1:3319     ESTABLISHED     2116
TCP    127.0.0.1:3319     127.0.0.1:3318     ESTABLISHED     2116

我们可以看到3318这个端口正在被pid为2116的程序占用,于是继续执行

tasklist|findstr “2116”

得到结果

firefox.exe      2116      Console      0      65,956 K

这样,我们就知道是firefox在占用这个端口了……但是奇怪的是,当我关掉firefox再重启,它也不会再继续占用我原来的端口了……可能是因为firefox会随机占用一下,所以导致我原来想使用的端口被占用吧……这不巧了么这不是啊?

然后,因为菜狗肉壳最近买了一台mac,所以考虑到mac也会出现这种情况,该怎么办呢?

mac下相对比较简单,只需要一条命令

lsof -i -n | grep 3318

这样就可以看到哪个程序占用了这些端口,就是这样……

Java,使用Jung包读取GraphML数据

最近在做一个Project,跟微博啥的有关,肉壳的工作就是给微博用户打分,看谁最重要,基本上就是简单的修改了一下Page Rank算法和HITS算法。不过第一步就是要把搭档给我的数据读出来。因为都是用户关系用网络表示,为了方便处理,前期操作都是把数据写在GraphML格式文件中。GraphML也是一种标记语言,跟HTML,XML什么的差不多,里面都是一些标签。有兴趣的话,大家自己Google一下就可以了……

搭档们用的都是R和Python,里面有包可以直接读GraphML,但是木讷的我不会用R和Python,只能在Java里找相关的包,结果还真找到一个叫Jung的包。这个包功能非常强大,可以对GraphML增删改查,还可以计算网络的PR,HITS什么的,可谓非常强大……不过今天就讲一些简单的,就是如何将GraphML文件中的数据读出来,就是这么简单……

首先,我们看一下GraphML的文件格式,

<graphml xmlns="http://graphml.graphdrawing.org/xmlns"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="d0" for="node" attr.name="color" attr.type="string">
    <default>yellow</default>
  </key>
  <key id="d1" for="edge" attr.name="weight" attr.type="double">
	<default>0.0</default>
  </key>
  <graph id="G" edgedefault="directed">
    <node id="n0">
      <data key="d0">green</data>
    </node>
    <node id="n1"/>
    <node id="n2">
      <data key="d0">blue</data>
    </node>
    <node id="n3">
      <data key="d0">red</data>
    </node>
    <node id="n4"/>
    <node id="n5">
      <data key="d0">turquoise</data>
    </node>
    <edge id="e0" source="n0" target="n2">
      <data key="d1">1.0</data>
    </edge>
    <edge id="e1" source="n0" target="n1">
      <data key="d1">1.0</data>
    </edge>
    <edge id="e2" source="n1" target="n3">
      <data key="d1">2.0</data>
    </edge>
    <edge id="e3" source="n3" target="n2"/>
    <edge id="e4" source="n2" target="n4"/>
    <edge id="e5" source="n3" target="n5"/>
    <edge id="e6" source="n5" target="n4">
      <data key="d1">1.1</data>
    </edge>
  </graph>
</graphml>

首先,key标签定义了Vertex和Edge的meta信息,以便以后获取到这些信息后将他们读出来。<graph id=”G” edgedefault=”directed”>定义里这个图是个有向图,不过我代码里用的是个无向图(undirected),大家使用的时候需要注意一下。之后运行一下下面的代码就好了。

GraphMLReader<undirectedgraph, Node, Edge> gmlr = new GraphMLReader<undirectedgraph, Node, Edge>(new VertexFactory(), new EdgeFactory()); //创建一个GrahpML的Reader
final UndirectedGraph graph = new UndirectedSparseMultigraph();

gmlr.load(filename, graph); //读取graph,并将内容写进graph对象

BidiMap vertex_ids = gmlr.getVertexIDs(); //获取Vertex的id
<Map> edge_meta = gmlr.getEdgeMetadata(); //获取Edge的内容

//graph对象此时只有Vertex和边的连接关系,我们需要把Vertex和Edge的附加信息写进去
for (Node n : graph.getVertices()) {
	n.setUserID(vertex_ids.get(n));
	n.setPageRank(0.2);
	n.setAuth(1);
	n.setHub(1);
}
for (Edge e : graph.getEdges()) {
	e.setCapacity(Double.parseDouble(edge_meta.get("d1").transformer.transform(e))); //读取的d2信息是在GraphML文件里定义的
}

经过这么一番简单操作,graph对象就已经包含了各个Vertex和Edge的关系了……就是这么简单……Vertex和Edge对象是自己写的,下面再贴个NodeFactory和EdgeFactory的代码。

class VertexFactory implements Factory {
	private int n = 0;

	public Node create() {
		return (new Node(n++));
	}
}

class EdgeFactory implements Factory {
	private int e = 0;

	public Edge create() {
		return (new Edge(e++));
	}
}

需要注意的时候,无向图读取以后,不知道是不是因为我不会用,每条Edge的from和target读不出来,用有向图就能读出来,好奇怪……不过大家到也不用担心,因为graph有个方法叫getEndpoints,可以获取到特定边的两个顶点,然后再操作就可以了……

另外,最近在研究GitHub,虽然早就注册了,但是一直没用过……现在想想,太狗了……

C#,用基本全局阈值法求图像二值化时的阀值

最近在学习Emgu CV,并重新复习C#,在图像处理中,有一个过程叫“二值化”,简单来说就是将图片的每个像素转换成1或0,以方便后面的边缘检测,但是在二值化的过程当中,有个很复杂的问题就是确定二值化的阀值,怎么获得这个阀值呢?肉壳在网上找了一些方法,其中一种叫基本全局阀值法。SkySeraph在他的文章中还提到了其他几种方法,不过都是用C++实现的,因为我比较低端不会C++,所以一直能抽一种自己需要的方法,修改成C#语言了……

因为今天也是我第一次用Emgu,所以不确定最终获得阀值的使用方法是否正确,大家帮忙看一下吧,错了别怪我……

/*=====基本全局阈值法=======*/
int BasicGlobalThreshold(int[] pg, int start, int end)
{
    int i, t, t1, t2, k1, k2;
    double u, u1, u2;
    t = 0;
    u = 0;
    for (i = start; i < end; i++)
    {
        t += pg[i];
        u += i * pg[i];
    }
    k2 = (int)(u / t); // 计算此范围灰度的平均值    
    do
    {
        k1 = k2;
        t1 = 0;
        u1 = 0;
        for (i = start; i <= k1; i++)
        { // 计算低灰度组的累加和
            t1 += pg[i];
            u1 += i * pg[i];
        }
        t2 = t - t1;
        u2 = u - u1;
        if (t1 != 0)
            u1 = u1 / t1; // 计算低灰度组的平均值
        else
            u1 = 0;
        if (t2 != 0)
            u2 = u2 / t2; // 计算高灰度组的平均值
        else
            u2 = 0;
        k2 = (int)((u1 + u2) / 2); // 得到新的阈值估计值
    } while (k1 != k2); // 数据未稳定,继续
    return (k1); // 返回阈值
}

这个是基本算法pg是直方图,start和end表示直方图的起始位置和结束位置,这段代码基本没改动过,只是把C++里的指针给弄没了……

//gray_image是变量
int i, thre;
int[] pg = new int[256];
for (i = 0; i < 256; i++) pg[i] = 0;
int w = gray_image.Width; // 获得图像的长和宽
int h = gray_image.Height;
//直方图统计
int[] hist_size = new int[1] { 256 }; // 建一个数组来存放直方图数据
IntPtr HistImg = CvInvoke.cvCreateHist(1, hist_size, Emgu.CV.CvEnum.HIST_TYPE.CV_HIST_ARRAY, null, 1); // 创建了一个空的直方图
IntPtr[] inPtr1 = new IntPtr[1] { gray_image };
CvInvoke.cvCalcHist(inPtr1, HistImg, false, System.IntPtr.Zero); // 计算inPtr1指向图像的数据
for (i = 0; i < 256; i++)
{
    pg[i] = (int) CvInvoke.cvQueryHistValue_1D(HistImg, i); // 将直方图数据放入数组
}
thre = BasicGlobalThreshold(pg, 0, 256); // 确定阈值
CvInvoke.cvThreshold(gray_image, gray_image, thre, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY); // 二值化

大概就是这样……