精华内容
下载资源
问答
  • 生物信息编程实战题

    千次阅读 2018-11-06 20:07:30
    1.生信编程很简单 编程语言系统入门 题目 下载安装bowtie2(内含测试数据) 2.人类基因组的外显子区域的长度 题目 测试数据 R实现代码示例 3.hg19基因组序列的一些探究 题目 测试数据 Perl代码示例 参考...

    目录

     

    1.生信编程很简单

    编程语言系统入门

    题目

    下载安装bowtie2(内含测试数据)

    2.人类基因组的外显子区域的长度

    题目

    测试数据

    R实现代码示例

    3.hg19基因组序列的一些探究

    题目

    测试数据

    Perl代码示例

    参考结果{-}

    4.hg38每条染色体的基因、转录本分布

    题目

    测试数据

    代码示例

    5.多个同样行列式文件的合并

    题目

    模拟数据

    真实数据

    代码示例

    6.根据GTF画基因的多个转录本结构

    题目

    测试数据

    R实现代码示例

    参考结果

    7.下载最新版的KEGG信息,并且解析好

    题目

    测试数据

    Perl代码示例

    参考结果

    8.写超几何分布检验

    题目

    测试数据

    R代码示例

    9.ID转换

    题目

    测试数据

    R代码示例

    10.根据指定染色体及坐标得到序列

    题目

    测试数据

    11.根据指定染色体及坐标得到位置信息

    题目

    测试数据

    12.把文件内容按照染色体分开写出

    题目

    测试数据

    Perl代码示例

    13.JSON格式数据的格式化

    题目

    测试数据

    Perl代码示例

    参考结果

    14.多个探针对应一个基因,取平均值、最大值

    题目

    测试数据

    R代码示例

    15.把counts矩阵转换成RPKM矩阵

    题目

    测试数据

    R代码示例

    参考结果

    16.对有临床信息的表达矩阵批量做生存分析

    题目

    代码示例

    17.对多个差异分析结果直接取交集并集

    题目

    测试数据

    R代码示例

    参考结果

    18.根据GTF格式的基因注释文件得到人所有基因的染色体坐标

    题目


    1.生信编程很简单

    编程语言系统入门

    题目

    对FASTQ的操作

    • 5,3段截掉几个碱基
    • 序列长度分布统计
    • FASTQ 转换成 FASTA
    • 统计碱基个数及GC%

    对FASTA的操作

    • 取互补序列
    • 取反向序列
    • DNA to RNA
    • 大小写字母形式输出
    • 每行指定长度输出序列
    • 按照序列长度/名字排序
    • 提取指定ID的序列
    • 随机抽取序列

    高级难度

    • 根据坐标取序列
    • 多文件合并
    • 根据ID列表取序列
    • GTF文件探索
    • 简并碱基的引物序列还原成多条序列
    • snp进行注释并格式化输出

    下载安装bowtie2(内含测试数据)

    cd ~/biosoft
    mkdir bowtie &&  cd bowtie
    wget https://sourceforge.net/projects/bowtie-bio/files/bowtie2/2.2.9/bowtie2-2.2.9-linux-x86_64.zip  
    unzip bowtie2-2.2.9-linux-x86_64.zip
    

    2.人类基因组的外显子区域的长度

    题目

    下载人类外显子的坐标文件,编写代码统计外显子区域的长度。

    测试数据

    • Rbioconductor的TxDb.Hsapiens.UCSC.hg19.knownGene包
    • NCBI数据库:ftp://ftp.ncbi.nlm.nih.gov/pub/CCDS/current_human/

    R实现代码示例

    rm(list=ls())
    a=read.table(choose.files(),sep = '\t',stringsAsFactors = F,header = T) # 选择你下的CCDs文件
    tmp <- apply(a[1:100,], 1, function(gene){ # 取前100行数据分析调试
    # gene=a[3,]
      x=gene[10] # Column10 外显子坐标位置列
      if(grepl('\\]',x)){ # 判断x中是否存在有]这样的符号,如果有就利用正则替换掉。
        x=sub('\\[','',x)
        x=sub('\\]','',x)
        # 这个时候得到的对象还是像这样的“880073-880179, 880436-880525……”
        tmp <- strsplit(as.character(x),',')[[1]]# 我们先从逗号开始分割成小块
        start <- as.numeric(unlist(lapply(tmp,function(y){# 取开始位点
          strsplit(as.character(y),'-')[[1]][1]
        })))
        end <- as.numeric(unlist(lapply(tmp,function(y){ # 取结束位点
          strsplit(as.character(y),'-')[[1]][2]
        })))
        gene_d <- data.frame(gene=gene[3], # 将基因名,染色体,开始、结束位点绑定为数据框
                          chr=gene[1],
                          start=start,
                          end=end
        )
        return (gene_d)#返回数据框
      }
    }) 
    tmp_pos=c() # 构造一个空的向量
    lapply(tmp[1:10], function(x){ # 取前10个list文件计算调试
    # print(x)
      if ( !is.null(x)){
        apply(x, 1,function(y){
          #print(y)
          for ( i in as.numeric(y[3]):as.numeric(y[4]) ) # y[3]为坐标起点,y[4]为终止坐标,历编
            tmp_pos <<- c(tmp_pos,paste0(y[2],"-",i))
        })
        
      }
    })
    length(tmp_pos) # 计算exon的长度
    length(unique(tmp_pos)) # 计算去重后的exon的长度
    

    3.hg19基因组序列的一些探究

    题目

    求:hg19 每条染色体长度,每条染色体N的含量,GC含量。 (高级作业:蛋白编码区域的GC含量会比基因组其它区域的高吗? )

    测试数据

    • hg19基因组序列下载
    wget http://hgdownload.cse.ucsc.edu/goldenPath/hg19/bigZips/chromFa.tar.gz # 也可以在浏览器上下载
    tar xvzf chromFa.tar.gz
    cat *.fa > hg19.fa
    rm chr*.fa # 先把着急删,我待会可能要那他测试运行速度
    
    • 简单测试数据
    >chr_1
    ATCGTCGaaAATGAANccNNttGTA
    AGGTCTNAAccAAttGggG
    >chr_2
    ATCGAATGATCGANNNGccTA
    AGGTCTNAAAAGG
    >chr_3
    ATCGTCGANNNGTAATggGA
    AGGTCTNAAAAGG
    >chr_4
    ATCGTCaaaGANNAATGANGgggTA
    

    Perl代码示例

    单行命令

    perl -alne '{if(/^>/){$chr=$_}else{ $A_count{$chr}+=($_=~tr/Aa//); $T_count{$chr}+=($_=~tr/Tt//);$C_count{$chr}+=($_=~tr/Cc//); $G_count{$chr}+=($_=~tr/Gg//); $N_count{$chr}+=($_=~tr/Nn//); }}END{print "$_\t$A_count{$_}\t$T_count{$_}\t$C_count{$_}\t$G_count{$_}\t$N_count{$_}" foreach sort keys  %N_count}' test.fa 
    

    完整代码

    while (<>){
    chomp;
    if(/^>/){
    $chr=$_
    }
    else{ 
    $A_count{$chr}+=($_=~tr/Aa//);
    $T_count{$chr}+=($_=~tr/Tt//);
    $C_count{$chr}+=($_=~tr/Cc//); 
    $G_count{$chr}+=($_=~tr/Gg//);
    $N_count{$chr}+=($_=~tr/Nn//); 
    }
    } 
    foreach (sort keys  %N_count){
    $length = $A_count{$_}+$T_count{$_}+$C_count{$_}+$G_count{$_}+$N_count{$_};
    $gc = ($G_count{$_}+$C_count{$_})/($A_count{$_}+$T_count{$_}+$C_count{$_}+$G_count{$_});
    print "$_\t$A_count{$_}\t$T_count{$_}\t$C_count{$_}\t$G_count{$_}\t$N_count{$_}\t$length\t$gc\n" 
    }
    

    参考结果{-}

    结果如下;

    >chr_1        13        10        7        10        4
    >chr_2        11        6        5        8        4
    >chr_3        10        6        3        10        4
    >chr_4        9        4        2        7        3
    

    4.hg38每条染色体的基因、转录本分布

    题目

    对GTF注释文件进行探究,统计每条染色体基因数、转录本数、内含子数、外显子数。

    高级作业:去ENSEMBL数据库 下载human/rat/mouse/dog/cat/chicken等物种的gtf注释文件编写函数实现对多个GTF文件进行批量统计染色体基因、转录本的分布及转录本外显子个数;

    继续探索回答以下问题:

    • 所有基因平均有多少个转录本?
    • 所有转录本平均有多个exon和intron?
    • 如果要比较多个数据库呢(gencode/UCSC/NCBI?)?
    • 如果把基因分成多个类型呢?protein coding gene,pseudogene,lncRNA还有miRNA的基因?它们的特征又有哪些变化呢?

    测试数据

    wget -c ftp://ftp.ensembl.org/pub/release-87/gtf/homo_sapiens/Homo_sapiens.GRCh38.87.chr.gtf.gz
    gzip -d Homo_sapiens.GRCh38.87.chr.gtf.gz
    

    代码示例

    # 每条染色体的基因个数
    zcat Homo_sapiens.GRCh38.87.chr.gtf.gz |perl -alne '{print if $F[2] eq "gene" }' |cut -f 1 |sort |uniq -c
    # 基因分类
    zcat Homo_sapiens.GRCh38.87.chr.gtf.gz |perl -alne '{next unless $F[2] eq "gene" ;/gene_biotype "(.*?)";/;print $1}'  |sort |uniq -c
    

    5.多个同样行列式文件的合并

    题目

    将htseq-count生成的所有独立样本文件进行合并(每个样品对应一个文件,包括了所有基因表达量)。 希望通过编程处理每个文件得到输出的表达矩阵(行名是基因名,列名是样品名),如下所示:

    模拟数据

    用perl脚本模仿htseq-count计算每个样本所有的基因表达量的输出独立样本文件:

    ## 首先新建文件tmp.sh 输入这个代码:
    perl -le '{print "gene_$_\t".int(rand(1000)) foreach 1..99}'
    ## 然后用perl脚本调用这个tmp.sh文件:
    perl -e 'system(" bash tmp.sh >$_.txt") foreach a..z'
    ## 这样就生成了a~z这26个样本的counts文件
    

    第一列是基因,第二列是该基因的counts值,共有a~z这26个样本的counts文件,需要合并成一个大的行列式,这样才能导入到R里面做差异分析,如果手工用excel表格做,当然是可以的,但是太麻烦,如果有500个样本,正常人都不会去手工做了,需要编程。

    每个样本的基因顺序并不一致,这时候你应该怎么做呢?

    真实数据

    实际需求如下:GSE48213里面有56个文件,需要合并成一个表达矩阵,来根据cell-line的不同,分组做差异分析。可以查看paper

    wget -c ftp://ftp.ncbi.nlm.nih.gov/geo/series/GSE48nnn/GSE48213/suppl/GSE48213_RAW.tar
    tar -xf GSE48213_RAW.tar
    gzip -d *.gz
    

    代码示例

    ## 首先在GSE48213_RAW目录里面生成tmp.txt文件,使用shell脚本:
    awk '{print FILENAME"\t"$0}' * |grep -v EnsEMBL_Gene_ID >tmp.txt
    ## 然后把tmp.txt导入R语言里面用reshape2处理即可!
    setwd('tmp/GSE48213_RAW/')
    a=read.table('tmp.txt',sep = '\t',stringsAsFactors = F)
    library(reshape2)
    fpkm <- dcast(a,formula = V2~V1)
    

    6.根据GTF画基因的多个转录本结构

    题目

    从NCBI,ENSEMBL,UCSC,GENCODE数据库下载各种GTF注释文件,编写代码得到所有基因的转录本个数,以及每个转录本的外显子的坐标,绘制如下转录本结构图:

    比如对这个ANXA1基因来说,非常多的转录本,但是基因的起始终止坐标,是所有转录本起始终止坐标的极大值和极小值。同时,它是一个闭合基因,因为它存在一个转录本的起始终止坐标等于该基因的起始终止坐标。可以看到它的外显子并不是非常整齐的,虽然多个转录本会共享某些外显子,但是也存在某些外显子比同区域其它外显子长的现象。

    测试数据

    wget -c http://www.broadinstitute.org/cancer/cga/sites/default/files/data/tools/rnaseqc/gencode.v7.annotation_goodContig.gtf.gz
    gzip -d gencode.v7.annotation_goodContig.gtf.gz
    

    R实现代码示例

    rm(list=ls())
    
    ## http://www.broadinstitute.org/cancer/cga/sites/default/files/data/tools/rnaseqc/gencode.v7.annotation_goodContig.gtf.gz
    
    setwd('tmp')
    gtf <- read.table('gencode.v7.annotation_goodContig.gtf.gz',stringsAsFactors = F,
                      header = F,comment.char = "#",sep = '\t'
                      )
    table(gtf[,2])
    gtf <- gtf[gtf[,2] =='HAVANA',]
    gtf <- gtf[grepl('protein_coding',gtf[,9]),]
    
    lapply(gtf[1:10,9], function(x){
      y=strsplit(x,';') 
    })
    
    gtf$gene <- lapply(gtf[,9], function(x){
      y <- strsplit(x,';')[[1]][5]
      strsplit(y,'\\s')[[1]][3]
      }
    )
    draw_gene = 'TP53'
    structure = gtf[gtf$gene==draw_gene,]
      
    colnames(structure) =c(
      'chr','db','record','start','end','tmp1','tmp2','tmp3','tmp4','gene'
    )
    gene_start <- min(c(structure$start,structure$end))
    gene_end <- max(c(structure$start,structure$end))
    tmp_min=min(c(structure$start,structure$end))
    structure$new_start=structure$start-tmp_min
    structure$new_end=structure$end-tmp_min
    tmp_max=max(c(structure$new_start,structure$new_end))
    num_transcripts=nrow(structure[structure$record=='transcript',])
    tmp_color=rainbow(num_transcripts)
    
    x=1:tmp_max;y=rep(num_transcripts,length(x))
    #x=10000:17000;y=rep(num_transcripts,length(x))
    plot(x,y,type = 'n',xlab='',ylab = '',ylim = c(0,num_transcripts+1))
    title(main = draw_gene,sub = paste("chr",structure$chr,":",gene_start,"-",gene_end,sep=""))
    j=0;
    tmp_legend=c()
    for (i in 1:nrow(structure)){
      tmp=structure[i,]
      if(tmp$record == 'transcript'){
        j=j+1
        tmp_legend=c(tmp_legend,paste("chr",tmp$chr,":",tmp$start,"-",tmp$end,sep=""))
      }
      if(tmp$record == 'exon') lines(c(tmp$new_start,tmp$new_end),c(j,j),col=tmp_color[j],lwd=4)
    }
    

    参考结果

    7.下载最新版的KEGG信息,并且解析好

    题目

    下载最新版的KEGG注释文本文件,编写脚本整理成kegg的pathway的ID与基因ID的对应格式。

    测试数据

    • 1 首先打开KEGG官方网站,网页中展示出了各个物种的分类、拉丁名称、英文名称等信息。

    • 2 直接网页中搜索(Ctrl + F)需要下载的物种英文名称或拉丁名。如果不确定物种名称,网站中提供了详细的分类系统,也可根据前面的物种分类信息进行查找。 本文以拟南芥为例,搜索“Arabidopsis thaliana”即可找到。找到后点击物种名称前的3个字母缩写链接(下图红色框中的位置)。

    • 3 进入后的网页中包含了物种的一些基因组信息,点击上方的“Brite hierarchy”,进入后再点击“KEGG Orthology (KO)”;

    • 4 在跳转出的网页中点击“Download htext”,弹出下载窗口进行下载,国外网站有时会出现无法下载的情况,多试几次即可;

    • 5 当然,下载好之后还没有结束。下载得到文本文件,可以看到里面的结构层次非常清楚,C开头的就是kegg的pathway的ID所在行,D开头的就是属于它的kegg的所有的基因。A,B是kegg的分类,总共是6个大类,42个小类。

    Perl代码示例

    perl -alne '{if(/^C/){/PATH:hsa(\d+)/;$kegg=$1}else{print "$kegg\t$F[1]" if /^D/ and $kegg;}}' hsa00001.keg >kegg2gene.txt
    

    参考结果

    8.写超几何分布检验

    题目

    学习GO/KEGG的富集分析的原理,编写代码实现超几何分布检验,将得到的结果与测试数据中的kegg.enrichment.html进行比较。

    (P值的计算:C(k,M)*C(n-k,N-M)/C(n,N) )

    测试数据

    • kegg2gene(第六讲kegg数据解析结果)

    暂时不用最新版的kegg注释数据,为了能够统一答案

    • 差异基因list和背景基因list(R代码)
    source("http://bioconductor.org/biocLite.R")
    biocLite("org.Hs.eg.db")
    biocLite("KEGG.db")
    biocLite("GOstats")
    biocLite("hgu95av2.db")
    
    library(org.Hs.eg.db)
    library(KEGG.db)
    library(GOstats)
    library("hgu95av2.db")
    
    ##得到kegg2gene.list(KEGG注释信息)
    
    tmp=toTable(org.Hs.egPATH)
    write.table(tmp,'kegg2gene.list.txt',quote = F,row.names = F)
    ## 得到universeGeneIds.txt(背景基因list)
    ls('package:hgu95av2.db')
    universeGeneIds <- unique(mappedRkeys(hgu95av2ENTREZID))
    write.table(universeGeneIds,'universeGeneIds.txt',quote = F,row.names = F)
    
    ## 得到diff_gene.txt(差异基因list)
    
    set.seed('123456.789')
    diff_gene = sample(universeGeneIds,300)
    write.table(diff_gene,'diff_gene.txt',quote = F,row.names = F)
    
    ## 得到kegg.enrichment.html(富集分析结果)
    
    annotationPKG='org.Hs.eg.db'
    hyperG.params = new("KEGGHyperGParams", geneIds=diff_gene, universeGeneIds=universeGeneIds, annotation=annotationPKG,
    categoryName="KEGG", pvalueCutoff=1, testDirection = "over")
    KEGG.hyperG.results = hyperGTest(hyperG.params);
    htmlReport(KEGG.hyperG.results, file="kegg.enrichment.html", summary.args=list("htmlLinks"=TRUE))
    
    

    R代码示例

    下载链接: https://github.com/jmzeng1314/humanid/blob/master/R/hyperGtest_jimmy.R

    library("hgu95av2.db")[/align][align=left]ls('package:hgu95av2.db')
    universeGeneIds <- unique(mappedRkeys(hgu95av2ENTREZID))
    set.seed('123456.789')
    diff_gene = sample(universeGeneIds,300)
    library(org.Hs.eg.db)
    library(KEGG.db)
    tmp=toTable(org.Hs.egPATH)
    GeneID2kegg<<- tapply(tmp[,2],as.factor(tmp[,1]),function(x) x)
    kegg2GeneID<<- tapply(tmp[,1],as.factor(tmp[,2]),function(x) x)
    #results <- hyperGtest_jimmy(GeneID2kegg,kegg2GeneID,diff_gene,universeGeneIds)
    
    GeneID2Path=GeneID2kegg
    Path2GeneID=kegg2GeneID
    
    diff_gene_has_path=intersect(diff_gene,names(GeneID2Path))
    n=length(diff_gene) #306
    N=length(universeGeneIds) #5870
    results=c()
    
    for (i in names(Path2GeneID)){
      #i="04672"
      M=length(intersect(Path2GeneID[[i]],universeGeneIds))
      #print(M)
      
      if(M<5)
        next
      exp_count=n*M/N
      #print(paste(n,N,M,sep="\t"))
      k=0
      for (j in diff_gene_has_path){
        if (i %in% GeneID2Path[[j]]) k=k+1
      }
      OddsRatio=k/exp_count
      if (k==0) next
      p=phyper(k-1,M, N-M, n, lower.tail=F)
      #print(paste(i,p,OddsRatio,exp_count,k,M,sep="    "))
      results=rbind(results,c(i,p,OddsRatio,exp_count,k,M))
    }
    colnames(results)=c("PathwayID","Pvalue","OddsRatio","ExpCount","Count","Size")
    results=as.data.frame(results,stringsAsFactors = F)
    results$p.adjust = p.adjust(results$Pvalue,method = 'BH')
    results=results[order(results$Pvalue),]
    rownames(results)=1:nrow(results)
    

    9.ID转换

    题目

    probe_id,gene_id,gene_name, symbol之间的转换。

    测试数据

    • 需要转换的探针ID(变量my_probe)
    rm(list=ls())
    library("hgu95av2.db")
    ls('package:hgu95av2.db')
    probe2entrezID=toTable(hgu95av2ENTREZID)
    probe2symbol=toTable(hgu95av2SYMBOL)
    probe2genename=toTable(hgu95av2GENENAME)
    
    my_probe = sample(unique(mappedLkeys(hgu95av2ENTREZID)),30)
    
    tmp1 = probe2symbol[match(my_probe,probe2symbol$probe_id),]
    tmp2 = probe2entrezID[match(my_probe,probe2entrezID$probe_id),]
    tmp3 = probe2genename[match(my_probe,probe2genename$probe_id),]
    
    write.table(my_probe,'my_probe.txt',quote = F,col.names = F,row.names =F)
    write.table(tmp1$symbol,'my_symbol.txt',quote = F,col.names = F,row.names =F)
    write.table(tmp2$gene_id,'my_geneID.txt',quote = F,col.names = F,row.names =F)
    
    • 下载对应关系 ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/
    • illumina芯片的探针

    所有bioconductor支持的芯片平台对应关系:通过bioconductor包来获取所有的芯片探针与gene的对应关系;可以从NCBI的GPL平台下载:http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GPL6947;也可以直接加载对应的包;或者直接去公司的主页下载manifest文件。

    library("illuminaHumanv4.db")
    ls('package:illuminaHumanv4.db')
    
    probe2entrezID=toTable(illuminaHumanv4ENTREZID)
    probe2symbol=toTable(illuminaHumanv4SYMBOL)
    probe2genename=toTable(illuminaHumanv4GENENAME)
    
    my_probe = sample(unique(mappedLkeys(illuminaHumanv4ENTREZID)),30)
    
    probe2symbol[match(my_probe,probe2symbol$probe_id),]
    probe2entrezID[match(my_probe,probe2entrezID$probe_id),]
    probe2genename[match(my_probe,probe2genename$probe_id),]
    
    

    R代码示例

    基因的转换:运行下面的R代码,得到的my_symbol_gene和my_entrez_gene就是需要转换的ID。

    library("illuminaHumanv4.db")
    ls('package:illuminaHumanv4.db')
    my_entrez_gene = sample(unique(mappedRkeys(illuminaHumanv4ENTREZID)),30)
    my_symbol_gene = sample(unique(mappedRkeys(illuminaHumanv4SYMBOL)),30)
    
    library("org.Hs.eg.db")
    ls('package:org.Hs.eg.db')
    
    entrezID2symbol <- toTable(org.Hs.egSYMBOL)
    
    entrezID2symbol[match(my_entrez_gene,entrezID2symbol$gene_id),]
    entrezID2symbol[match(my_symbol_gene,entrezID2symbol$symbol),]
    

    10.根据指定染色体及坐标得到序列

    题目

    参考基因组hg19,指定染色体及坐标"chr5","8397384",编写程序得到这个坐标以及它上下一个碱基。(机器无法计算hg19,则使用测试数据,指定坐标是 3号染色体的第6个碱基。)

    测试数据

    >chr_1
    ATCGTCGaaAATGAANccNNttGTA
    AGGTCTNAAccAAttGggG
    >chr_2
    ATCGAATGATCGANNNGccTA
    AGGTCTNAAAAGG
    >chr_3
    ATCGTCGANNNGTAATggGA
    AGGTCTNAAAAGG
    >chr_4
    ATCGTCaaaGANNAATGANGgggTA
    

    11.根据指定染色体及坐标得到位置信息

    题目

    基因的chr,start,end都是已知的(坐标是hg38系统),任意给定基因组的chr:pos(chr1:2075000-2930999), 判断该区间在哪个基因上面?(可用现成软件bedtools)

    测试数据

    chr7        148697841        148698941
    chr7        148698942        148699029
    chr7        148699911        148701053
    chr7        148701109        148701307
    chr7        148701354        148702694
    chr7        148703100        148703520
    chr7        148703831        148704175
    chr7        148704484        148704734
    chr7        148704857        148705937
    chr7        148706271        148706671
    

    12.把文件内容按照染色体分开写出

    题目

    根据染色体把文件拆分成1~22和其它染色体的两个文件呢?

    测试数据

    wget ftp://ftp.ncbi.nlm.nih.gov/pub/CCDS/current_human/CCDS.current.txt
    

    把文件改成bed格式,如下:

    chr2    43995310    43995986
    chr17  49788603    49789067
    chr17  59565573    59566163
    chr19  8390308 8390745
    chr12  49188033    49189033
    chr7    974903  975570
    chr7    98878532    98879500
    chr7    44044672    44045322
    chr1    153634052  153634772
    chr11  60905850    60906575
    

    Perl代码示例

    use FileHandle;
    foreach( 1..22 ){
        $normal_chr{"chr".$_}=1 ;
        open $fh{"chr".$_},">chr$_.txt" or die;
    }
    open other,">chr_other.txt" or die;
    open FH,'a.bed';
    while(<FH>){
        chomp;
        @F=split;
        if(exists $normal_chr{$F[0]}){
            $fh{$F[0]}->print( "$_\n" );
        }else{ 
            print other $_;
        }
    }
    foreach( 1..22 ){ 
        close $fh{$_};
    }
    close other;
    

    13.JSON格式数据的格式化

    题目

    学习json格式,下载测试数据,从该json文件里面提取:technique factor target principal_investigator submission label category type Developmental-Stage organism key这几列信息。

    测试数据

    http://biotrainee.com/jbrowse/JBrowse-1.12.1/sample_data/json/modencode/modencodeMetaData.json

    Perl代码示例

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use autodie ':all';
    use 5.10.0;
    
    use JSON 2;
    
    my $data = from_json( do { local $/; open my $f, '<', $ARGV[0]; scalar <$f> } );
    
    my @fields = qw( technique factor target principal_investigator submission label category type Developmental-Stage organism key );
    
    say join ',', map "\"$_\"", @fields;
    
    for my $item ( @{$data->{items}} ) {
        $item->{key} = $item->{label};
        no warnings 'uninitialized';
        for my $track ( @{$item->{Tracks}} ) {
            $item->{label} = $track;
            say join ',', map "\"$_\"", @{$item}{@fields};
        }
    }
    

    参考结果

    完成之后的结果应该是:http://biotrainee.com/jbrowse/JBrowse-1.12.1/sample_data/json/modencode/modencodeMetaData.csv

    14.多个探针对应一个基因,取平均值、最大值

    题目

    编写脚本对多个探针对应一个基因,取平均值、最大值。

    测试数据

    R里面的包自带很多芯片表达数据,所以测试数据就在下面的R代码里面

    R代码示例

    # 平均值
    BiocInstaller::biocLite('CLL')
    BiocInstaller::biocLite('hgu95av2.db')
    
    library('hgu95av2.db')
    library(CLL)
    data(sCLLex)
    sCLLex=sCLLex[,1:8] ## 样本太多,我就取前面8个
    group_list=sCLLex$Disease
    exprSet=exprs(sCLLex)
    exprSet=as.data.frame(exprSet)
    exprSet$probe_id=rownames(exprSet)
    head(exprSet)
    probe2symbol=toTable(hgu95av2SYMBOL)
    dat=merge(exprSet,probe2symbol,by='probe_id')
    results=t(sapply(split(dat,dat$symbol),function(x) colMeans(x[,1:(ncol(x)-1)])))
    
    

    15.把counts矩阵转换成RPKM矩阵

    题目

    编写脚本将hisat2+htseq-counts之后得到reads的counts矩阵转换成RPKM矩阵。

    测试数据

    wget ftp://ftp.ncbi.nlm.nih.gov/pub/CCDS/current_mouse/CCDS.current.txt
    grep -v '^#' CCDS.current.txt | perl -alne '{/\[(.*?)\]/;$len=0;foreach(split/,/,$1){@tmp=split/-/;$len+=($tmp[1]-$tmp[0])};$h{$F[2]}=$len if $len >$h{$F[2]}} END{print "$_\t$h{$_}" foreach sort keys %h}' >mm10_ccds_length.txt
    

    R代码示例

    genes_len=read.table("mm10_ccds_length.txt",stringsAsFactors=F)
    head(genes_len)
                  V1    V2
    1      -343C11.2  1139
    2 00R_AC107638.2  1060
    3      00R_Pgap2  1676
    4  0610005C13Rik  7363
    5  0610006L08Rik 34995
    6  0610007P14Rik  9074
    
      
    colnames(genes_len)<- c("GeneName","Len")
    
     head(exprSet)
                  GSM860181_priSG-A GSM860182_SG-A GSM860183_SG-B GSM860184_lepSC
    00R_AC107638.2                0              1              0              1
    0610005C13Rik                20            22            11              27
    0610006L08Rik                  0              0              0              2
    0610007P14Rik              2075          1785          1269            1430
    0610009B22Rik                256            376            300            386
    0610009E02Rik                22            22            16              28
      
    exprSet<-exprSet[ rownames(exprSet) %in% genes_len$GeneName ,]
    
    total_count<- colSums(exprSet)
    
    neededGeneLength=genes_len[  match(rownames(exprSet), genes_len$GeneName) ,2] 
      
    rpkm <- t(do.call( rbind,lapply(1:length(total_count),function(i){
            10^9*exprSet[,i]/neededGeneLength/total_count[i]
    }) ))
    head(rpkm)
    rownames(rpkm)=rownames(exprSet)
    colnames(rpkm)=colnames(exprSet)
    
    write.table(rpkm,file="rpkm.txt",sep="\t",quote=F)
    
      
      
    library(TxDb.Mmusculus.UCSC.mm10.knownGene)
    txdb=TxDb.Mmusculus.UCSC.mm10.knownGene
    gt=transcriptsBy(txdb,by="gene")
    lapply(gt[1:40],function(x) max(width(x)))
    library(org.Mm.eg.db)
    
    mykeys=
    columns(txdb);keytypes(txdb)
    neededcols <- c("GENEID", "TXSTRAND", "TXCHROM")
    select(txdb, keys=mykeys, columns=neededcols, keytype="TXNAME")
    

    参考结果

    16.对有临床信息的表达矩阵批量做生存分析

    题目

    使用R实现生存分析: 用my.surv <- surv(OS_MONTHS,OS_STATUS=='DECEASED')构建生存曲线; 用kmfit2 <- survfit(my.surv~TUMOR_STAGE_2009)来做某一个因子的KM生存曲线; 用survdiff(my.surv~type, data=dat)来看看这个因子的不同水平是否有显著差异,其中默认用是的logrank test 方法; 用coxph(Surv(time, status) ~ ph.ecog + tt(age), data=lung) 来检测自己感兴趣的因子是否受其它因子(age,gender等等)的影响。

    代码示例

    rm(list=ls())
    ## 50 patients and 200 genes 
    dat=matrix(rnorm(10000,mean=8,sd=4),nrow = 200)
    rownames(dat)=paste0('gene_',1:nrow(dat))
    colnames(dat)=paste0('sample_',1:ncol(dat))
    os_years=abs(floor(rnorm(ncol(dat),mean = 50,sd=20)))
    os_status=sample(rep(c('LIVING','DECEASED'),25))
    
    library(survival)
    my.surv <- Surv( os_years,os_status=='DECEASED')
    ## The status indicator, normally 0=alive, 1=dead. Other choices are TRUE/FALSE (TRUE = death) or 1/2 (2=death). 
    ## And most of the time we just care about the time od DECEASED . 
    
    fit.KM=survfit(my.surv~1)
    fit.KM
    plot(fit.KM)
    
    log_rank_p <- apply(dat, 1, function(values1){
      group=ifelse(values1>median(values1),'high','low')
      kmfit2 <- survfit(my.surv~group)
      #plot(kmfit2)
      data.survdiff=survdiff(my.surv~group)
      p.val = 1 - pchisq(data.survdiff$chisq, length(data.survdiff$n) - 1)
    })
    names(log_rank_p[log_rank_p<0.05])
    
    gender= ifelse(rnorm(ncol(dat))>1,'male','female')
    age=abs(floor(rnorm(ncol(dat),mean = 50,sd=20)))
    ## gender and age are similar with group(by gene expression)
    
    cox_results <- apply(dat , 1, function(values1){
      group=ifelse(values1>median(values1),'high','low')
      survival_dat <- data.frame(group=group,gender=gender,age=age,stringsAsFactors = F)
      m=coxph(my.surv ~ age + gender + group, data =  survival_dat)
      
      beta <- coef(m)
      se <- sqrt(diag(vcov(m)))
      HR <- exp(beta)
      HRse <- HR * se
      
      #summary(m)
      tmp <- round(cbind(coef = beta, se = se, z = beta/se, p = 1 - pchisq((beta/se)^2, 1),
                        HR = HR, HRse = HRse,
                        HRz = (HR - 1) / HRse, HRp = 1 - pchisq(((HR - 1)/HRse)^2, 1),
                        HRCILL = exp(beta - qnorm(.975, 0, 1) * se),
                        HRCIUL = exp(beta + qnorm(.975, 0, 1) * se)), 3)
      return(tmp['grouplow',])
      
    })
    cox_results[,cox_results[4,]<0.05]
    

    PS: 里面的os_years应该修改为os_month,因为总的生存期不应该长达几十年,而且因为ag和os_years都是随机生成的,可能会出现很不符合自然科学的现象。但是这个是模拟数据,请大家不用较真。

    17.对多个差异分析结果直接取交集并集

    题目

    编写脚本对每两个差异分析结果计算基因交集个数与基因并集个数的比值,得到一个比值矩阵。

    测试数据

    用perl单行命令模拟数据:

    perl -e 'BEGIN{use List::Util qw/shuffle/;@gene=A..Z}{foreach(1..10){@this_genes=@gene[(shuffle(0..25))[0..int(rand(20))+4]];print "comparison_$_ <-  ";print join(";",@this_genes);print "\n"}}'
    

    总共10次差异分析,每次差异分析得到的差异基因在同一行的后面用大小字母表示。

    comparison_1 -> I;G;E;V;C;K;B;W
    comparison_2 -> G;E;N;H;Y;M;L;S;K;A;J;O;D;P;R;U;Q;F;Z;C
    comparison_3 -> Y;V;U;N;H;K;I;P;S;F;D;X;G;C;Z;J;Q;T;W;O;E;M
    comparison_4 -> N;T;K;B;H;Z;W;C;Q;I;V;F;D;S;R;Y;J;X;P;O;G;L;A
    comparison_5 -> G;J;A;H;W;T;Z;E;Y;S;R
    comparison_6 -> Z;M;D;R;P;G;L;W;Y;U;X;E;A;S;T;I;H
    comparison_7 -> H;Z;T;O;W;Q;M;X;J;N;U;K;F;P;I;C;S;Y;A;B
    comparison_8 -> A;R;L;T;W;Q;S;F;P;X;E;V;Y;G;K;J;Z;C
    comparison_9 -> J;X;K;D;O;H;L;F;C;P;R;N
    comparison_10 -> G;S;K;H;C;O;W;F;Q;X
    

    R代码示例

    a=readLines('test.txt')
    n=unlist(lapply(a , function(x){
      trimws(strsplit(x,'<-')[[1]][1])
    }))
    v=lapply(a , function(x){
      trimws(strsplit(trimws(strsplit(x,'<-')[[1]][2]),';')[[1]])
    })
    names(v)=n
    tmp=unlist(lapply(v, function(x){
      lapply(v, function(y){
        p1=length(intersect(x,y))
        p2=length(union(x,y))
        return(p1/p2)
      })
    }))
    out=matrix(tmp,nrow = length(n))
    rownames(out)=n
    colnames(out)=n
    out[1:5,1:5]
    

    参考结果

    结果的前五行如下:

    comparison_1 comparison_2 comparison_3 comparison_4 comparison_5
    comparison_1    1.0000000    0.1666667    0.3043478    0.2916667    0.1875000
    comparison_2    0.1666667    1.0000000    0.6800000    0.6538462    0.4090909
    comparison_3    0.3043478    0.6800000    1.0000000    0.7307692    0.3750000
    comparison_4    0.2916667    0.6538462    0.7307692    1.0000000    0.4166667
    comparison_5    0.1875000    0.4090909    0.3750000    0.4166667    1.0000000
    

    18.根据GTF格式的基因注释文件得到人所有基因的染色体坐标

    题目

    从gencode数据库里面可以下载所有的gtf文件,编写脚本得到基因的染色体、起始终止坐标如下:

    [jianmingzeng@gencode]$ head protein_coding.hg19.position 
    chr1        69091        70008        OR4F5
    chr1        367640        368634        OR4F29
    chr1        621096        622034        OR4F16
    chr1        859308        879961        SAMD11
    chr1        879584        894689        NOC2L
    chr1        895967        901095        KLHL17
    chr1        901877        911245        PLEKHN1
    chr1        910584        917473        PERM1
    chr1        934342        935552        HES4
    chr1        936518        949921        ISG15
    [jianmingzeng@gencode]$ head protein_coding.hg38.position 
    chr1        69091        70008        OR4F5
    chr1        182393        184158        FO538757.2
    chr1        184923        200322        FO538757.1
    chr1        450740        451678        OR4F29
    chr1        685716        686654        OR4F16
    chr1        923928        944581        SAMD11
    chr1        944204        959309        NOC2L
    chr1        960587        965715        KLHL17
    chr1        966497        975865        PLEKHN1
    chr1        975204        982093        PERM1
    展开全文
  • 利用BIOS的硬件信息编程(1)

    千次阅读 2016-12-30 23:40:13
    使用已有磁盘新建一台虚拟机,启动虚拟机,查看屏幕输出信息: 现在设置磁盘的第一个扇区为启动扇区MBR. #vim mbr.asm start: times (510-($-$$)) db 0 ;510字节前面都设置为0,$表示当前地址,$$...

    1.为什么要有BIOS这个东西


    BIOS实际就是ROM里面的一段小程序(芯片总容量大概就是几M),在主板通电时候会硬件加载执行。基本功能就是进行硬件检测,检查没问题就引导bootloader和系统。

    为什么需要这个?

    第一个原因,即使只有一块主板,什么外部连接的存储介质(磁盘,U盘等存储)都没有(更别说操作系统),这种情况下,一个主板其实也应该能进行一些硬件检查( 甚至是设置),这就是BIOS存在并且嵌入到主板的一个原因。再者,不同主板不一样的硬件配置,对应的bios代码也不一样。不过两个不同bios,对外提供统一的一些统一的操作硬件的接口,他们遵循bios规范【http://blog.chinaunix.net/uid-27033491-id-3239348.html】,以前的操一些操作系统例如DOS就是直接使用bios提供的硬件接口访问硬件,现在的linux访问硬件就是绕过bios访问硬件,下面我们会测试通过bios去访问硬件。

    2.bios加载MBR扇区

    首先主板通电,硬件自动加载bios程序。bios程序检查硬件,初始化和设置硬件,然后加载磁盘(启动盘)的MBR扇区到0x7c00,然后跳到0x7c00执行。为什么是0x7c00?可以看【http://www.ruanyifeng.com/blog/2015/09/0x7c00.html】。主要是兼容历史的原因。


    3.什么是启动扇区?

    一个磁盘分为多个磁面,一个磁面一个head(读写磁头),一个磁面多个磁道(track),一个磁道多个扇区(sector),一个扇区512字节。其中0磁头0磁盘第一个扇区称为这个磁盘的第一个扇区。如果这个扇区(512字节)最后两个字节是0xaa55.识别这个扇区是MBR主启动扇区。

    现在我们就来测试一下bios去加载MBR扇区的流程。

    我们这里使用redhat7.2的qemu虚拟化来做实验最为简单。

    首先新建一块1G的虚拟磁盘:

    qemu-img create -f qcow2 /home/disk.qcow2 2G

    使用已有磁盘新建一台虚拟机,启动虚拟机,查看屏幕输出信息:


    现在设置磁盘的第一个扇区为启动扇区MBR.

    #vim mbr.asm

    start:
    times (510-($-$$)) db 0 ;510字节前面都设置为0,$表示当前地址,$$表示起始地址
    dw 0xaa55               ;511和512字节设置为AA55,表示启动扇区

    编译:nasm mbr.asm -o mbr
    这个文件现在我们的磁盘的第一个扇区:
    由于qcow2是一个虚拟磁盘文件。我们需要通过nbd把虚拟磁盘文件挂在为真正可以访问的磁盘的。默认centos是没有nbd 安装nbd驱动。
    这里需要编译一下内核的nbd驱动:
    查看内核版本:
    # uname -a
    Linux bogon 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
    #wget http://vault.centos.org/7.2.1511/os/Source/SPackages/kernel-3.10.0-327.el7.src.rpm
    #rpm2cpio kernel-3.10.0-327.el7.src.rpm |cpio -imd
    #tar xvf linux-3.10.0-327.el7.tar.xz
    增加内核编译选项

    Device Drivers  ---> 
    [*] Block devices  ---> 
    <M>   Network block device support
    # make
    #insmod drivers/block/nbd.ko max_part=8
    # qemu-nbd -c /dev/nbd0 /home/disk.qcow2     ----------------虚拟磁盘文件挂在为真正的磁盘设备
    # dd if=./mbr of=/dev/nbd0 bs=1 count=512     ----------------把上面的程序mbr写入磁盘的头512字节,也就是第一个扇区
    #qemu-nbd -d /dev/nbd0

    重启启动虚拟机,虚拟机的屏幕输出:


    这说明bios已经识别到磁盘的MBR分区并且已经把MBR分区加载到了0x7c00地址执行。


    3.利用执行MBR扇区的代码实现键盘操作功能。

    现在处理器的控制权已经在mbr扇区代码的手里。现在我们就可以通过mbr扇区的代码去控制我们的处理器,进而操作我们的主板。

    现在我们就实现键盘的操作功能,其实bios已经有相关的键盘的接口提供。但是我们目前先不用它的接口。我们直接操作我们的键盘。

    目前我的键盘是ps2接口的键盘, 使用的ps2控制器是Intel的8042.


    所以我们先链接一下ps2接口,以及连接的电路图。


    键盘链接ps2插头:


    电脑ps2控制器连接图:



    上面两个图整合为一个整体就是:


    我们cpu可以控制ps2控制器8042进而控制我们的键盘。所以我们需要了解一下ps2的协议以及8042的芯片资料。其中ps2协议可以了解一下时钟信号和数据信号(电信号)的一些传输协议,当然这些信号我们只需要了解就行,因为这些信号ps2控制器可以帮我们处理,我们只要操作ps2控制器。ps2协议可以自己百度,这里只提供一下数据传输的信号:


    电信号采集数据要不就是高电平(二进制1),要不就是低电平(二进制0),上面8个数据刚好可以组成一个字节的数据。控制器就是通过这些信号和键盘进行通信的。当然,这是控制器的工作,我们可以重点不放在这里【有兴趣可以自己百度一下"ps2协议"或者"ps2 protocol"】。我们重点看如何操作ps2控制器。现在我们看一下8042控制器的操作:

    这里有一篇不错的介绍文章:http://blog.chinaunix.net/uid-25099259-id-3409632.html

    8042控制器的寄存器有四个:状态寄存器,输出缓存控制器,输入缓冲控制器,控制寄存器。我们通过处理器操作端口就可以控制8042寄存器:

    IO Port Access Type Purpose
    0x60 Read/Write Data Port
    0x64 Read Status Register
    0x64 Write Command Register

    关于寄存器的 每一个位的意思,可以看一下这个文章【http://wiki.osdev.org/%228042%22_PS/2_Controller】,里面有详细的寄存器信息介绍,还有如何初始化和使用控制器。我们就参考这边文章来操作的我们的寄存器。由于汇编不好,代码可能写的有点不精简。

    开始之前我们需要先要调试工具。例如读取到数据我们如何知道数据是什么?

    通过显示是最直观的。显示暂时没有去研究,我们可以直接使用bios提供的显示接口。例如打印0xaa,怎么打印?代码如下

    代码写的有点挫,熟悉的人可以修改一下:

    start: jmp run
    tran_ascii:;数字转为对应的ASCII
            cmp al,9
            jle add_30h
    	jmp add_57h
    add_30h:
            add al,0x30;eg:0的ASCII 0x30
            ret
    add_57h:
            add al,0x57;eg:a的ASCII 0x61
            ret
    print_8bit:;dl has data need print,eg:0xAB
    	push ax
    	push bx
    	push cx
    	push dx
    	xor ax,ax ;clear
    	xor bx,bx
    	mov al,dl ;被除数
    	mov bl,16 ;除数
    	div bl;AL存储除法操作的商,AH存储除法操作的余数
    	;把要打印的数据先保存起来
    	mov di,need_print
    	stosw
    
    	;显示高四位
    	mov ah,0x09
    	mov bh,0 ;显示页码
    	mov cx,1 ;重复输出字符的次数
    	call tran_ascii
    	int 0x10;功能描述:在当前光标处按指定属性显示字符
    
    	;移动光标到下一处
    	mov ah,0x03;读取当前光标位置
    	int 0x10
    	add dl,1;移动光标到下一处
    	mov ah,0x02
    	mov bh,0
    	int 0x10
    
    	;显示低四位
    	mov si,need_print
    	lodsw
    	mov al,ah
    	mov ah,0x09
    	mov cx,1 ;
    	call tran_ascii
    	int 0x10
    	pop dx
    	pop cx
    	pop bx
    	pop ax
    	ret
    
    need_print: DW 0x00
    run:
    	mov dl,0x1b
    	call print_8bit
    	times (510-($-$$)) db 0


    有了这个我们就可以打印出控制器端口读出来的数据了。下面开始真正编码操作ps2控制器:

    start: jmp run
    ;
    ;数字转为对应的ASCII
    tran_ascii:
            cmp al,9
            jle add_30h
    	jmp add_57h
    add_30h:
            add al,0x30;eg:0的ASCII 0x30
            ret
    add_57h:
            add al,0x57;eg:a的ASCII 0x61
            ret
    
    print_8bit:
    	push ax
    	push bx
    	push cx
    	push dx
    
    	;dl has data need print,eg:0xAB
    	xor ax,ax ;clear
    	xor bx,bx
    	mov al,dl ;被除数
    	mov bl,16 ;除数
    	div bl;AL存储除法操作的商,AH存储除法操作的余数
    	;save
    	mov di,need_print
    	stosw
    
    ;移动光标到下一处
            mov ah,0x03;读取当前光标位置
            int 0x10
            add dl,1;移动光标到下一处
            mov ah,0x02
            mov bh,0
            int 0x10
    
    	;显示high四位
    	mov si,need_print
            lodsw
    	mov ah,0x09
    	mov bh,0 ;显示页码
    	mov cx,1 ;重复输出字符的次数
    	call tran_ascii
    	int 0x10;功能描述:在当前光标处按指定属性显示字符
    	;移动光标到下一处
    	mov ah,0x03;读取当前光标位置
    	int 0x10
    	add dl,1;移动光标到下一处
    	mov ah,0x02
    	mov bh,0
    	int 0x10
    
    	;显示low四位
    	mov si,need_print
    	lodsw
    	mov al,ah
    	mov ah,0x09
    	mov cx,1 ;
    	call tran_ascii
    	int 0x10
    
    	pop dx
    	pop cx
    	pop bx
    	pop ax
    	ret
    wait_data:
    	in al,0x64
    	and al,1b
    	jz wait_data
    	in al,0x60
    	ret
    	
    
    
    need_print: DW 0x00
    
    run:
    	cli
    	;Disable Devices
    	mov al,0xad
            out 0x64,al
    	;Flush The Output Buffer
    flush_data:
    	in al,0x64
    	and al,0x01
    	jz flush_ok
    	in al,0x60
    	jmp flush_data
    flush_ok:
    	;Set the Controller Configuration Byte	
    	mov al,0x20;read configure 
    	out 0x64,al
    	in al,0x60
    	mov dl,al
    	add dl,11101100b;disabled interrupt,use poll mode
            mov al,0x60;set configure
    	out 0x64,al
    
    	mov al,dl
    	out 0x60,al
    	;Perform Controller Self Test
    	mov al,0xaa
    	out 0x64,al
    	call wait_data
    	cmp al,0x55
    	jne err
    	;Enable Devices
    	mov al,0xae ;first port for keyboard
            out 0x64,al
    test_port_1:
    	mov al,0xAB
    	out 0x64,al
    	call wait_data
    	cmp al,0x00
    	jne err
    read_input:
    	call wait_data 
    	mov dl,al
    	call print_8bit
    	jmp read_input
    err:
    	times (510-($-$$)) db 0
    	dw 0xaa55




    上面就是键盘输入:bear和ctl+alt的扫描码输出。

    各个按键的扫描码可以查看:http://wiki.osdev.org/PS/2_Keyboard

    0x30 B pressed
    0xB0 B released
    0x12 E pressed

    0x92 E released
    0x1E A pressed
    0x9E A released
    0x13 R pressed
    0x93 R released
    0x1D left control pressed
    0x38 left alt pressed
    0xB8 left alt released
    0x9D left control released







    展开全文
  • 网络编程学习笔记一:Socket编程

    万次阅读 多人点赞 2013-03-21 01:11:11
    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那...

    “一切皆Socket!”

    话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。

    ——有感于实际编程和开源项目研究。

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的。本文的主要内容如下:

    • 1、网络中进程之间如何通信?
    • 2、Socket是什么?
    • 3、socket的基本操作
      • 3.1、socket()函数
      • 3.2、bind()函数
      • 3.3、listen()、connect()函数
      • 3.4、accept()函数
      • 3.5、read()、write()函数等
      • 3.6、close()函数
    • 4、socket中TCP的三次握手建立连接详解
    • 5、socket中TCP的四次握手释放连接详解
    • 6、一个例子(实践一下)
    • 7、留下一个问题,欢迎大家回帖回答!!!

    1、网络中进程之间如何通信?

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

    • 消息传递(管道、FIFO、消息队列)
    • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
    • 共享内存(匿名的和具名的)
    • 远程过程调用(Solaris门和Sun RPC)

    但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址可以唯一标识网络中的主机,而传输层的“协议+端口可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

    使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX  BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

    2、什么是Socket?

    上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

    socket一词的起源

    在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

    3、socket的基本操作

    既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

    3.1、socket()函数

    int socket(int domain, int type, int protocol);

     socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

    正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

    • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INETAF_INET6AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
    • type:指定socket类型。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等等(socket的类型有哪些?)。
    • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

    注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

    当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()listen()时系统会自动随机分配一个端口。

    3.2、bind()函数

    正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INETAF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    函数的三个参数分别为:

    • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
    • addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是: 
      struct sockaddr_in {
          sa_family_t    sin_family; /* address family: AF_INET */
          in_port_t      sin_port;   /* port in network byte order */
          struct in_addr sin_addr;   /* internet address */
      };
      
      /* Internet address. */
      struct in_addr {
          uint32_t       s_addr;     /* address in network byte order */
      };

      ipv6对应的是: 

      struct sockaddr_in6 { 
          sa_family_t     sin6_family;   /* AF_INET6 */ 
          in_port_t       sin6_port;     /* port number */ 
          uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
          struct in6_addr sin6_addr;     /* IPv6 address */ 
          uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
      };
      
      struct in6_addr { 
          unsigned char   s6_addr[16];   /* IPv6 address */ 
      };

      Unix域对应的是: 

      #define UNIX_PATH_MAX    108
      
      struct sockaddr_un { 
          sa_family_t sun_family;               /* AF_UNIX */ 
          char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
      };

       

    • addrlen:对应的是地址的长度。

    通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

    网络字节序与主机字节序

    主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

      a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

      b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

    所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

    3.3、listen()、connect()函数

    如果作为一个服务器,在调用socket()bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

    int listen(int sockfd, int backlog);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

    connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

    3.4、accept()函数

    TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

    注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

    3.5、read()、write()等函数

    万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

    • read()/write()
    • recv()/send()
    • readv()/writev()
    • recvmsg()/sendmsg()
    • recvfrom()/sendto()

    我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

           #include <unistd.h>
    
           ssize_t read(int fd, void *buf, size_t count);
           ssize_t write(int fd, const void *buf, size_t count);
    
           #include <sys/types.h>
           #include <sys/socket.h>
    
           ssize_t send(int sockfd, const void *buf, size_t len, int flags);
           ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    
           ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen);
           ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);
    
           ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
           ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

    write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

    其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

    3.6、close()函数

    在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

    #include <unistd.h>
    int close(int fd);

    close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

    注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

    4、socket中TCP的三次握手建立连接详解

    我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

    • 客户端向服务器发送一个SYN J
    • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
    • 客户端再想服务器发一个确认ACK K+1

    只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

    image

    图1、socket中发送的TCP三次握手

    从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

    总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

    5、socket中TCP的四次握手释放连接详解

    上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

    image

    图2、socket中发送的TCP四次握手

    图示过程如下:

    • 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
    • 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
    • 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
    • 接收到这个FIN的源发送端TCP对它进行确认。

    这样每个方向上都有一个FIN和ACK。

    6、一个例子(实践一下)

    说了这么多了,动手实践一下。下面编写一个简单的服务器、客户端(使用TCP)——服务器端一直监听本机的6666号端口,如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接并发送一条消息。

    服务器端代码:

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h>
    #define MAXLINE 4096 int main(int argc, char** argv) { int listenfd, connfd; struct sockaddr_in servaddr; 
    char buff[4096]; int n;
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(6666); 
    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){ printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    if( listen(listenfd, 10) == -1){ printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    printf("======waiting for client's request======\n"); 
    while(1){ if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){ printf("accept socket error: %s(errno: %d)",strerror(errno),errno); continue; } n = recv(connfd, buff, MAXLINE, 0); buff[n] = '\0'; 
    printf("recv msg from client: %s\n", buff); close(connfd); } close(listenfd); }

    客户端代码:

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> 
    #define MAXLINE 4096 int main(int argc, char** argv) { int sockfd, n; char recvline[4096], sendline[4096]; 
    struct sockaddr_in servaddr; if( argc != 2){ printf("usage: ./client <ipaddress>\n"); exit(0); } if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("create socket error: %s(errno: %d)\n", strerror(errno),errno); 
    exit(0); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(6666); if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){ printf("inet_pton error for %s\n",argv[1]); exit(0); } 
    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("connect error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    printf("send msg to server: \n"); fgets(sendline, 4096, stdin); 
    if( send(sockfd, sendline, strlen(sendline), 0) < 0) { printf("send msg error: %s(errno: %d)\n", strerror(errno), errno); exit(0); } close(sockfd); exit(0); }

    当然上面的代码很简单,也有很多缺点,这就只是简单的演示socket的基本函数使用。其实不管有多复杂的网络程序,都使用的这些基本函数。上面的服务器使用的是迭代模式的,即只有处理完一个客户端请求才会去处理下一个客户端的请求,这样的服务器处理能力是很弱的,现实中的服务器都需要有并发处理能力!为了需要并发处理,服务器需要fork()一个新的进程或者线程去处理请求等。

    7、动动手

    留下一个问题,欢迎大家回帖回答!!!是否熟悉Linux下网络编程?如熟悉,编写如下程序完成如下功能:

    服务器端:

    接收地址192.168.100.2的客户端信息,如信息为“Client Query”,则打印“Receive Query”

    客户端:

    向地址192.168.100.168的服务器端顺序发送信息“Client Query test”,“Cleint Query”,“Client Query Quit”,然后退出。

    题目中出现的ip地址可以根据实际情况定。

    ——本文只是介绍了简单的socket编程。

    更为复杂的需要自己继续深入。

    (unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误(一个实际socket编程中遇到的问题,希望对你有帮助)

     

     

    作者:吴秦
    出处:http://www.cnblogs.com/skynet/
    本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).

    http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

     

    展开全文
  • Revit编程如何提取轴线信息

    千次阅读 2013-04-16 10:47:40
    Solution:这个问题在Revit编程时是非常典型的应用情况。找到目标对象,然后获取目标对象上的信息。找到目标对象需要使用Revit的过滤机制,最核心的也是比用的类就是FilteredElementCollector类,他提供了添加过滤...


    问题描述:


    在Revit里面如何提取当前视图中轴网的信息,例如名称,标高,坐标等等?



    Solution:


    这个问题在Revit编程时是非常典型的应用情况。找到目标对象,然后获取目标对象上的信息。


    找到目标对象需要使用Revit的过滤机制,最核心的也是比用的类就是FilteredElementCollector类,他提供了添加过滤条件的方法,并且提供方法来获取满足条件的对象集合。

    获取对象信息需要用Revit类的属性以及Revit对象的参数值,还有从Element.Location属性获取对象的位置信息。

    这些的讲座信息你可以从 这个视频讲座中获取Revit编程最基本知识:  http://download.autodesk.com/media/adn/Revit_2011_API_DevTV_Chinese.zip 

    从这个讲座里面获取Revit编程比较完整的描述如何读取参数信息,对象位置信息等:http://download.autodesk.com/media/adn/Revit2011_new_API_webcast(Chinese).zip



    下面是实例代码如何获取上述信息。

      [Transaction(TransactionMode.Manual)]
      public class GetAllGrids : IExternalCommand
      {
    
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
          UIApplication uiApp = commandData.Application;
          Application app = uiApp.Application;
          UIDocument uiDoc = uiApp.ActiveUIDocument;
          Document doc = uiDoc.Document;
    
    
          FilteredElementCollector collector = new FilteredElementCollector(doc,doc.ActiveView.Id);
          collector.OfClass(typeof(Grid));
    
    
          string sInfo = null;
          foreach (Element elem in collector)
          {
            sInfo += "Name = " + elem.Name + ";";
            
            Grid grid = elem as Grid;
            LocationCurve locCurve = grid.Location as LocationCurve;
            Curve cur = locCurve.Curve;
    
    
            XYZ ptStart = cur.get_EndPoint(0);
            XYZ ptEnd = cur.get_EndPoint(0);
          }
    
    
          TaskDialog.Show("Grid message", sInfo);
             
    
    
          return Result.Succeeded;
        }
      
    }


    转载请复制以下信息:
    原文链接: http://blog.csdn.net/joexiongjin/article/details/8807449
    作者:  叶雄进 , Autodesk ADN





    展开全文
  • VS编程之查看数组信息

    千次阅读 2017-01-17 10:29:37
    文章描写了VS编程中如何查看数组的所有信息,在代码调试的过程中很有用,可以为编程人员提供很大的帮助。
  • 本课程主要讲解了一些获取linux系统信息的函数,譬如获取时间相关的函数群,获取伪随机数序列的函数群和proc文件系统,目标是让大家学习相应的API和库函数,将来在项目中能够熟练应用之。
  • WINAPI 编程获取文件版本信息

    千次阅读 2009-04-15 13:01:00
    WINAPI 编程获取文件版本信息cheungmine本文演示如何使用win32 api 编写获得文件描述和产品版本。很简单的小程序。下面就是全部代码:test.c//// test.c// by cheungmine//#include #include #define DLLFILE "C://...
  • 编程编程语言

    2018-09-17 10:35:38
    相应的语言叫做汇编语言,而这个层次上的编程叫做汇编语言编程。 不同处理器的汇编语言只能用于为该处理器编写程序。汇编语言通常都与CPU的指令一一对应,能够以特定方式将指令编码为二进制格式,也知道信息在...
  • VC++ MFC编程版本信息控制

    千次阅读 2015-10-15 14:06:21
    个人博客地址 www.tmbcode.comVC++ MFC编程版本信息控制一、工程中添加版本信息 绿色框内为文件本件(FileVersion),红色框为产品版本(ProductVersion),两者的区别是一个文件可能包含多个产品,所以一般我们是...
  • Qt网络编程之获取网络信息

    千次阅读 2016-12-29 12:42:51
    在网络编程中经常需要获取本地或远程主机的网络信息,如IP地址、子网掩码、广播地址等,Qt network模块中提供了一些方便的类,如QHostInfo、QNetworkInterface等。 本文将从三种情况介绍Qt网络编程中如何获取主机...
  • 本次课程采用黑客网络编程使用为频繁的语言Python,通过使用Python的网络相关的模块来实现网络监听,以及不同层不同协议的过滤和解析。 在网络监听和数据包解析的基础上,学会过滤关键数据,达到提取用户隐私信息的...
  • 最牛的IT编程信息网站

    千次阅读 2013-08-13 17:58:14
    最牛的IT编程信息网站 CSDN csdn.net Alexa周排名:478百度权重:PR:反链数:3720   网站简介:CSDN.NET- 全球最大中文IT社区,为IT专业技术人员提供最全面的信息传播和服务平台 1 得分:3432查看榜单 ...
  • 职工分为正式和临时,实发工资是工资+津贴+奖金-税-住房公积金等等。临时工=工资+奖金-税
  • 【网络编程】Socket网络编程基础

    千次阅读 2019-06-12 21:41:50
    网络编程从大的方面说就是对信息的发送到接收 通过操作相应Api调度计算机硬件资源,并利用传输管道(网线)进行数据交换的过程 更为具体的涉及:网络模型、套接字、数据包 网络模型 – 对应关系 具体细节看一看我的...
  • 编程4年-Win32编程-基础编程-界面...联系方式:手机:13617621007博客:www.mantianx.com (满天下,有本人最新信息)E 妹:sunwangme@gmail.comQ Q :42489549MSN :sunwangme@hotmail.com关键词:Win32 桌面编程
  • Java 网络编程

    万次阅读 多人点赞 2019-05-30 23:07:18
    首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大,功能强的...
  • [信息图]编程语言的演化过程

    千次阅读 2018-05-31 08:53:42
    下面由Services Angle制作的信息图展示了过去数十年来编程语言的演化过程。大型机盛行的60年代开始出现高级编程语言,大大提高了代码编写效率,然后是微机、网络和现在的云计算时代,相继出现结构化、面向...
  • 使用V4L2编程获取摄像头设备信息

    千次阅读 2018-04-06 15:59:57
    如果想进一步了解V4L2编程,可以访问V4L2编程帮助手册官网 http://v4l.videotechnology.com/dwg/ 或者在我的网盘上下载 https://pan.baidu.com/s/15gmKHxXrXqT-lCr5HnVYVQ 里面包含了所有关于...
  • 信息的数学解释以及matlab编程

    万次阅读 2016-03-30 20:46:50
    1.互信息信息信息论中的一个基本概念,通常用于描述两个系统间的统计相关性,或者是一个系统中所包含另一个系统中信息的多少。 引入互信息对图像进行配准是因为:不需要假定两幅图像灰度的对应关系,不需要...
  • Ptython编程中忽略警告信息

    千次阅读 2017-11-12 16:14:46
    Python使用过程中忽略警告信息源博客链接Python的警告信息有时候很烦人,特别是因为软件版本引起的警告,下面的代码可以去掉python输出的警告:import warnings warnings.filterwarnings("ignore")
  • Linux编程获取系统信息内核版本

    千次阅读 2015-09-23 20:44:37
    Linux编程获取系统信息内核版本代码无私的共享 #include #include #include #include int main() { char computer[256]; struct utsname uts; if (gethostname(computer,255) != 0 || uname(&uts) ) { ...
  • Java编程思想(十四) —— 类型信息
  • 信息学奥林匹克竞赛-编程语言

    千次阅读 2015-11-17 13:15:53
    主流编程语言简介  计算机语言的种类非常的多,总的来说可以分成 机器语言,汇编语言,高级语言 三大类。 机器语言:是直接用二进制代码指令表达的计算机语言,指令是用0和1组成的一串代码,它们有一定的位数...
  • 编程题 数据库内的学生信息 POJ

    千次阅读 2016-11-28 11:16:39
    北京大学POJ 编程题 数据库内的学生信息 std::multimap,value>::iterator,所以这里直接在MyMultiple类中用typedef 重命名 自定义greater类模板
  • Java Socket编程 - 获取WEB站点主页信息

    千次阅读 2012-10-31 23:15:50
    早就有想写一个Java Socket编程系列的文章,由于自己懒一直没动。决定从 今天开始,每周写一篇,从最简单的socket连接,到文件传输到协议实现,到 远程桌面控制,全面讲述Java socket编程的各个方面与各种技巧,从...
  • Java编程思想(二)第14章-类型信息

    千次阅读 2018-01-06 21:50:36
    Java编程思想(二)第14章-类型信息 Java编程思想(三)第15章-泛型 Java编程思想(四)第17章-容器深入研究 Java编程思想(五)第18章-Java IO系统 Java编程思想(六)第19章-枚举类型 Java编程思想(七)第20...
  • 005:编程填空:学生信息处理程序

    千次阅读 2017-10-29 20:00:07
    005:编程填空:学生信息处理程序 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 1024kB 描述 实现一个学生信息处理程序,计算一个学生的四年平均成绩。要求实现一个代表学生的类,并且类中所有成员变量都是...
  • JavaBean编程思想-读取数据库信息

    千次阅读 2014-11-01 14:26:38
    前面我也说过,JavaBean就是实现了:把html代码和java代码分开,在html只需要调用该java...首先我们来看看JDBC(详情见另一篇博客JDBC编程基本)直接连接数据库显示在页面上的情况: 学号姓名院系 <%
  • Python GUI编程-学生信息管理系统

    千次阅读 2020-05-19 20:05:44
    实现学生信息的增加,删除,修改,查询功能 界面显示 主界面 添加界面 删除界面 修改界面 查询界面 from PyQt5 import QtWidgets,QtGui,QtCore from PyQt5.QtWidgets import * from menu ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 64,086
精华内容 25,634
关键字:

信息编程