openSUSE 12.1 配置工作环境[3]

作者:Ajian 发布时间:March 31, 2012 分类:openSUSE

  今天是基本环境配置的最后一篇,主要是细节的环境,更多的跟运维工作需求相关,当然使用者和开发者也可以得到一样的方便。

History 条数设置
因为是自己的工作环境 所以history的条数设置多点也没有问题。方便自己查看。
vim /etc/profile
if test -z "$PROFILEREAD" ; then
HISTSIZE=5000
export HISTSIZE
fi
另外还可以设置history的显示时间 不过默认openSUSE就是这样的。服务器上倒是要设置下。

剪切板条数设置
configure klipper
剪切板是一个很好的复制的工具,会存储所有复制过的内容 如果想粘贴或者重复利用之前复制过的内容就可以直接在剪切板里面找 就可以了 而且还可以进行搜索,默认的条数只有10条吧 太少了。根本满足不了我的需求。最大值设置到2040 好像就不能再大了。

klipper

konsole 快捷方式 样式调整
Konsole 是方便的终端软件,开新的tab 默认是ctrl+alt+t 但 firefox和chrome都了是ctrl+T 所以要修改下konsole的快捷方式 修改方式类似之前说的修改kopete查看消息的方式

System 配置
Link 链接dropbox同步的配置文件
linux-htd5:~ # ln -s Dropbox/System/bashrc .bashrc
linux-htd5:~ # ln -s Dropbox/System/bash_profile .bash_profile
linux-htd5:~ # ln -s Dropbox/System/vimrc .vimrc

~/.bashrc

 

#各种自己的服务器环境变量和自定义命令缩写
. /home/server/private/towiki/.hostlist_variable.tmp
#go语言的path路径
PATH=$PATH:/root/go/bin
export PATH

~/.bash_profile

#!/bin/bash
#we'd like it to cache
#keychain的配置
/usr/bin/keychain ${HOME}/.ssh/id_rsa
source ${HOME}/.keychain/${HOSTNAME}-sh > /dev/null

#go的环境变量
export GOROOT=$HOME/go
export GOARCH=amd64
export GOOS=linux

 

运维管理工具
keychain

相当方便的工具,可以让两个client之间进行通讯只要他们有相同的pub key  

安装 zypper in keychain


cssh  

全称cluster ssh 是可以多窗口同时操作的工具
http://sourceforge.net/projects/clusterssh/
wget http://cdnetworks-kr-1.dl.sourceforge.net/project/clusterssh/1.%20ClusterSSH%20Series%203/3.28/clusterssh-3.28.tar.gz
tar zxvf clusterssh-3.28.tar.gz
cd clusterssh-3.28/
cat README
可以查看安装方法 依赖perl module有
Tk
X11::Protocol
zypper in perl-Tk perl-X11-Protocol -y

运行 cssh 后面接多个IP 或者user@IP 最好是建立key 不然得单独分别输入密码

之前cssh的截图文章 Linux超强的批处理管理工具--CSSH

pssh 

全称 Parallel SSH Tools
http://code.google.com/p/parallel-ssh/%E3%80%80
wget http://parallel-ssh.googlecode.com/files/pssh-2.3.1.tar.gz
tar zxvf pssh-2.3.1.tar.gz
cd pssh-2.3.1
python setup.py install

使用详细查看 之前写的文章Linux超强的批处理工具--pssh(parallel-ssh) 

还有一个类似的软件叫onall 而且也有他自己的特点 有兴趣可以找找。

最后推荐一个网站 有完整的中文翻译和使用相关的内容 虽然是对openSUSE 11.4的新的一样试用:

http://libitum.org/opensuse-guide

openSUSE 12.1 配置工作环境[2]

作者:Ajian 发布时间:March 30, 2012 分类:openSUSE

 

   继续上次的,都是临时写的,平时也只是记录一些命令和过程,可能会有笔误,上一篇也稍微做了些修改。希望有人可以一起讨论和分享。

PS:默认安装的primary语言为English Secondary 为Chinese 这样比较好是因为英文的报错 更容易查找,并且英语的文档比较多些,同样不会影响中文的使用,尤其在系统安装的时候就应该安装上这样就会有跟中文设置相关的一些安装。

KDE升级4.8
先升级下KDE桌面,默认是4.7,升级到KDE4.8
添加KDE48的源 并且让/etc/zypper/repos.d 里面只留下 该源还有update non-oss oss 这四个源 

[KDE48]
name=KDE48
enabled=1
autorefresh=0
baseurl=http://download.opensuse.org/repositories/KDE:/Release:/48/openSUSE_12.1/
type=rpm-md
keeppackages=0

执行命令 zypper dup
如果有软件冲突 取舍下安装完就基本可以了。

安装zimwiki
zimwiki 是一个我比较喜欢的桌面wiki,可以很方便的随手记录相关的文档, 而且基本符合wiki的格式,最主要的是他的存储方式是文本的,所以可以在终端下直接写,甚至对于dropbox的同步也是相关方便。

http://zim-wiki.org/
wget http://zim-wiki.org/downloads/zim-0.55.tar.gz
依赖的包
gtk+ >= 2.6
python >= 2.5
python-gtk
python-gobject
python-simplejson (for python < 2.6)
python-xdg (optional, but recommended)
xdg-utils (optional, but recommended)
确认这些安装了之后 设置变量
XDG_DATA_HOME=/usr/local/share
export XDG_DATA_HOME
解压进入安装
./setup.py install
zim 启动 选择目录dropbox内的note目录 就可以看到更新的笔记了
系统重启后可以在菜单里面找到zim到时再拉到任务栏中 如图一样放置就可以了。


Selection_010.png

gmail 插件
Gmail是桌面插件gmail的邮件提醒工具,相关的方便 。Add Widgets → Get New Widgets -> 搜索gmail 安装就可以了
安装完后 有点小细节的配置 ,需要注意 Label 留空 Username 填写账号就可以了 不需要 @gmail.com 还可以进行misc的配置 如调整检查时间为1min检查一次


Selection_003.png

还可以发现更多的Widgets。

Radiotray安装
配置的时候来点音乐不错 ,网络收音机,安装方法是 参考swyear 的 http://swyear.blogspot.com(正常是看不到的 这个你懂的 这个blog有更多的openSUSE的内容)
# zypper in radiotray radiotray-lang
台湾相关的网络电台
http://dl.dropbox.com/u/6331820/radiotray-bookmarks.xml
下载下来改名为 bookmark.xml 放在 ~/.local/share/radiotray/

正常播放需要gstreamer相关的插件
搜索如下的软件进行安装
gstreamer-0_10-ffmpeg
gstreamer-0_10-fluendo-mp3
gstreamer-0_10-plugins-bad
gstreamer-0_10-plugins-ugly
(以上必修,以下可选)
还可以
gstreamer-0_10-fluendo-mpegdemux
gstreamer-0_10-fluendo-mpegmux
gstreamer-0_10-plugins-bad-orig-addon
gstreamer-0_10-plugins-good-extra
gstreamer-0_10-plugins-ugly-orig-addon

我经常听kiss radio ,推荐给你。

同步kopete历史消息
kopete 经常使用gmail MSN 很有原来聊天的一些历史记录,这些历史记录尤其在工作上的可能在回忆的时候可以帮助很大 所以我一般都是将聊天记录在dropbox进行自动同步的。
先创建好账号后
cd /root/.kde4/share/apps/kopete
ln -s /root/Dropbox/System/notebook_kopete_logs logs
/root/Dropbox/System/notebook_kopete_logs 是我在dropbox同步保持的日志目录
对于gmail除了这样保存历史,默认在gmail邮箱里面也是可以保存的。但对于有多账号的如MSN保存在kopete的历史记录里面很好 而且查询相当的方便。

Kopete配置

默认的kopete的配置直的非常不喜欢 在配置里面必需设置

显示用户头像: 在Contact List  勾选 Use contact photos when available

同一组的消息显示在一个窗口: Behavior 的Chat 选项卡 选择 Group Messages From Contacts in Same Group in Same Chat Window

当然你想改变字体窗口样式都可以。

还有查看消息的快捷键:在Setting --> Configure Shortcuts Setting -->search : read 修改custom:为Alt+w 这个是我的习惯  KDE下所有的软件都有本地快捷方式和全局快捷方式 可以方便的进行配置。其它软件同样的方法进行修改。

snapshot6.png

System Tray 修改
可能是因为升级了4.8不知道为什么kopete会默认的隐藏起来,有时候为马上看到消息就会不知道了。
所以需要将kopete设置总是可见
操作:右键 System Tray 就是声音 剪切版的位置 System Tray Setting ,将kopete改为Always Visible 其它的了可以 想自动隐藏的 想总是可见的都可以设置


snapshot5.png

Rss阅读同步
因为我订阅了很多RSS 如果每次换个电脑又要重新来会很麻烦,当然有人要说Google在线的阅读 我还是比较习惯本地的阅读 所以没办法了。
启动Personal Informastion Magnager 需要启动akonadi服务 默认不让root启动该服务。如果不启动这个很多依赖的软件无法正常工作
如何用ROOT用户启动akonadi?
I encounter the same errors too. Actually, I am using Gentoo. As fduraibi mentioned, it is just because mysqld can't start as root. I add "user=root" in the Akonadi local mysql configuration file (on my computer, it is /root/.local/share/akonadi/mysql.conf), and Akonadi server can be started successfully.
修改/root/.local/share/akonadi/mysql.conf 在最后添加user=root即可。
再进行链接
cd /root/.kde4/share/apps/akregator/data
ln -s /root/Dropbox/System/feeds.opml .
重新启动就可以看到一样的RSS了。

chromium(chrome) for root
右键开始菜单Edit Applications 找到chromium(chrome) 在 command一行中添加像如下
chromium %u --user-data-dir=/opt/googlecache

Selection_004.png

(待续...)

openSUSE 12.1 配置工作环境[1]

作者:Ajian 发布时间:March 28, 2012 分类:openSUSE

     我使用openSUSE已经有快5年了 ,对于他也是情有独钟,满足了我对炫丽桌面的需求,也可以很稳定的提供使用环境,虽然中间也经历了很多版本的变化和无数的折腾,但总体还是很不错的,中间因为openSUSE的版本对我的笔记本无线网卡不支持 用了大半年的Ubuntu 相对来说Ubuntu很是活跃而且社区支持和文档都比较多,但我本人不是太喜欢Gnome 还有debian系统的结构也不是很习惯 最主要是受不了每天大量的软件更新,经常还会更新之后出现想不到的bug。openSUSE 他的管理界面和结构都比较清晰 而且跟我管理的服务器的结构没有太大的差异 使用还是比较方便。这次我主要介绍下openSUSE 12.1 配置我的工作环境的细节 ,算是一个check list 。现在基本上拿任何一台电脑都可以很方便的同步我的工作环境 ,而且也符合我自己的工作习惯,读者可以当成一种借鉴。

安装openSUSE 12.1之后 ,我主要是习惯了使用root 所以很多配置都是需要修改的。安装的时候不要建立其它账号 直接设置root密码就可以了。(虽然直接使用root不是好的习惯 但至今还没有做过一件错事 当然你就不要学我了 哈哈) 接下来按顺序配置openSUSE


配置源:

 

Add Software Repositories

zypper ar http://mirrors.magnetjoychina.com/opensuse/distribution/12.1/repo/non-oss/ magnetjoy_opensuse12.1_non-oss
zypper ar http://mirrors.magnetjoychina.com/opensuse/distribution/12.1/repo/oss/ magnetjoy_opensuse12.1_oss
zypper ar http://mirrors.magnetjoychina.com/opensuse/update/12.1/ magnetjoy_opensuse12.1_update

我使用的是公司自己做的mirror mirror会在半夜进行同步 白天就可以很快的进行更新 如果想使用国内比较快的源可以将 magnetjoychina 替换成 sohu就可以了。

还要打开yast -> Software Repositories  去掉默认的update oss non-oss 和光盘安装时候的cd 源

进行zypper up

安装Dropbox :

安装dropbox 主要是因为 我保存了很多东西在dropbox里面,这个是我的一个核心文档,dropbox除了有各个项目的文档 还有我的工作环境 操作系统的各种配置文件 如:repositories vim配置文件 bashrc .bash_profile kopete日志 RSS文档 等等 只有了这些我才可以很快的时行配置,甚至我可以写一个自动的脚本 就可以很方便的复制工作环境了。

安装脚本kde-dropbox.sh:

#!/bin/bash
test -d /usr/lib64 && myarch="x86_64" || myarch="x86"
echo "Install dropbox (arch: $myarch) without nautilus in KDE4"
echo "Please make sure you have a dropbox account!"
echo "Continue ? (y or n)"
read yn
if [ $yn == "y" ]; then
echo "Installing ..."
#wget -N -O dropbox-$myarch.tar.gz http://www.dropbox.com/download/?plat=lnx.$myarch
tar -zxof dropbox-$myarch.tar.gz
mv .dropbox-dist ~
echo "Do you want to startup Dropbox automatically when login? (y or n)"
read autoyn
if [ $autoyn == "y" ]; then
ln -s ~/.dropbox-dist/dropboxd ~/.kde4/Autostart/
fi
echo "Do you want to add Dropbox startup to your menu? (y or n)"
read menuyn
if [ $menuyn == "y" ]; then
echo "Icon=$HOME/.dropbox-dist/dropbox.png" >> dropbox.desktop
echo "Exec=$HOME/.dropbox-dist/dropbox start -i" >> dropbox.desktop
mkdir -p ~/.local/share/applications
mv dropbox.desktop ~/.local/share/applications/
mv dropbox.png ~/.dropbox-dist/
fi
echo "Starting setup ..."
~/.dropbox-dist/dropboxd &
echo "Done!"
fi

注意 因为在国内dropbox会有被阻止,所以我一般都是将脚本中的wget那句注释,想办下载dropbox-$myarch.tar.gz之后 再执行脚本 就可以方便的进行安装 并且自启动。

安装dropbox后,输入账号和密码 同步内容到本地。

添加额外的源:

可以编辑一个自己的repo文件如:myrepo.repo 存放到/etc/zypper/repos.d

[download.videolan.org-SuSE]
name=VideoLan Repository
enabled=0
autorefresh=0
baseurl=http://download.videolan.org/pub/videolan/vlc/SuSE/12.1/
path=/
type=rpm-md
keeppackages=0
[Packman Repository]
name=Packman Repository
enabled=1
autorefresh=0
baseurl=http://packman.inode.at/suse/openSUSE_12.1/
type=rpm-md
keeppackages=0
[subpixel]
name=subpixel
enabled=1
autorefresh=0
baseurl=http://opensuse-community.org/subpixel/openSUSE_12.1
path=/
type=rpm-md
keeppackages=0
[swyear]
name=swyear
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/home:/swyear/openSUSE_12.1
path=/
type=rpm-md
keeppackages=0
[home:swyear:shutter]
name=home:swyear:shutter
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/home:/swyear:/shutter/openSUSE_12.1/
type=rpm-md
keeppackages=0

 

安装常用软件:

有一些常用的必要软件,可以在一开始就进行安装。

 

install need software
zypper in ibus mplayer smplayer umplayer radiotray shutter per-Proc-Simple w32codec-all libxine1-codec stardict dia kdesvn subversion git vim-enhanced virtualbox opera chromium

ibus 输入法 

mplayer相关的播放器

w32codec-all libxine1-codec 编码 有它们才可以播放不同的视频

stardict 本地字典

dia 类似visio可以方便的创建自己的拓扑图

radiotray 收音机 还需要安装一些其它的软件gstream相关的

shutter 一个很好的截图和编程软件 ksnapshot 虽然可以很方便的截图 但是没有编辑

virtualbox 虚拟机

opera 浏览器

chromium chrome google的浏览器

subversion svn版本控制管理 现在在用的

git git版本管理工具 将要使用的

 

Shutter安装:

一键安装:http://software.opensuse.org/ymp/home:swyear/openSUSE_12.1/shutter.ymp

因为要写这篇文章所以 首先要有一个截图工具 shutter就排在了安装首位 我是按我的安装顺序来记录的。

如果在安装shutter的时候需要perl的依赖问题 可以添加一些perl的 源

[devel:languages:perl]
name=devel:languages:perl
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/devel:/languages:/perl/openSUSE_12.1/
type=rpm-md
keeppackages=0

我遇到一个问题:

linux-htd5:~/Dropbox/my # shutter
Failed to open file '/usr/share/shutter/resources/icons/sel_window_tooltip.svg': No such file or directory at /usr/share/shutter/resources/modules/Shutter/App/Menu.pm line 533, <DATA> line 19.


安装完后就没有这个文件,但是就是要这个文件才可以打开 简单的给他一个空名字也可以

linux-htd5:/usr/share/shutter/resources/icons # cp sel_window.svg sel_window_tooltip.svg


修改KDE界面和字体:

修改KDE界面 其实集成得已经相当不错了。全部都可以在 Configure Desktop 里面搞定。

修改字体: Configure Desktop - > Application Appearance ->Fonts 设置DPI 和 anti-aliasing 选择自己喜欢的字体和大小

当然也可以自己安装雅黑 Linux安装微软雅黑字体

还可以在swyear 的源里面安装有关ttf的包 如chinese-font 符合汉字相关的一些字体

snapshot2.png

配置命令快捷方式:

使用alt+F2可以很方便的 调用出想要的命令和软件甚至是文档 ,不过我不喜欢默认的样式 可以通过设置 实现如下的界面

snapshot4.png

配置默认的session:

默认openSUSE 启动都会将上次关闭的应用全部打开,还是重启登陆之后有一个干净的界面会比较喜欢。

Configure Desktop -> Startup and Shutdown  ->  Session Management选择 start with empty session

Selection_009.png

在autostart 可以设置自启动的相关脚本 Service Manager 可以关闭不需要的自启动服务 如apper  这个自动的更新服务很是麻烦 

(今天就写到这 明天继续... )

 

Golang : TCP Chat Server and Client 聊天服务程序

作者:Ajian 发布时间:March 27, 2012 分类:Golang

最近在学习Go,如果有C语言功底是很容易接触go语言的,但是我是一个运维之前写的大部分程序都是面向过程的shell python脚本类型语言,对c也不是太熟悉,所以接触Go还是有些吃力的,尤其是涉及网络传输,channel ,指针,结构等术语的时候,再加上GO的中文教程和demo都比较少,还有相当的晕。我还是使用我的学习方法,用一个实际需求例子来一学习,当然首先还是要过一遍GO发布的基础教学的。

ps:使用的是r60的版本编译的,后来发现Go1的有很多变化,以后相关的go程序还是要标示出当时的版本

需求:使用TCP协议写一个多人同时在线聊天服务,包括服务端和客户端

参考网站:

Golang Away: TCP Chat Server //基本能用 server端但我进行了一些小的修改和优化 去了些多余的东西

simpler chat server and client in golang //基本不能用 client 有很多的语法错误 不过可以一步步排查

Server:

package main                                                                                              
//这个是必需的 独立运行的执行文件必需使用                                                                 
import "fmt"
import "net"
import "container/list"
import "bytes"
//加载其它的库                                                                                            
//fmt 实现格式化的I/O 类似printf                                                                         
//net 实现网络协议TCP UDP 在这里使用TCP                                                                   
//container/list 实现双向链表队列                                                                         
//bytes 字符数组操作相关功能                                                                              
                                                                                                          
type Client struct {                                                                                      
    //定义一个结构 struct 用于抽象数据类型                                                                
    Name string                                                                                           
    Incoming chan string                                                                                  
    Outgoing chan string                                                                                  
    Conn net.Conn                                                                                         
    Quit chan bool
    ClientList *list.List
}

//go可以返回多个值  使用括号()
func (c *Client) Read(buffer []byte) (int, bool) {
    bytesRead,error := c.Conn.Read(buffer)
    //:= 同时定义和赋值,并且可以同时多个变量
    if error != nil {
        //nil is like C's NULL
        c.Close()
        Log(error)
        return 0, false
        //返回的值为bool类型
    }
    Log("Read ",bytesRead," bytes")
    return bytesRead, true
}

func (c *Client) Close(){
    c.Quit <- true
    //管道传递true给Quit
    c.Conn.Close()
    c.RemoveMe()
    //调用RemoveMe func
}

//Equal 帮助对比client
func (c *Client) Equal(other *Client) bool{
    if bytes.Equal([]byte(c.Name),[]byte(other.Name)){
        if c.Conn == other.Conn{
            return true
        }
    }
    return false
}

func (c *Client) RemoveMe(){
    for entry := c.ClientList.Front();entry != nil ; entry = entry.Next(){
        //双向链表队列的使用
       client := entry.Value.(Client)
       if c.Equal(&client){
            Log("RemoveMe: ",c.Name)
            c.ClientList.Remove(entry)
       }
    }
}

//...可变数组 在屏幕输出日志
//interface 代表任意数据类型 Everything in Go is derived from interface, so in theory, this can be any datatype.
func Log(v... interface{}){
    fmt.Println(v...)
}

func IOHandler(Incoming <- chan string,clientList *list.List){
    for {
        //在go里面没有while do ,for可以无限循环
        Log("IOHandler: Waiting for input")
        input := <- Incoming 
        Log("IOHandler: Handling ",input)
        for e := clientList.Front(); e != nil; e= e.Next(){
            client := e.Value.(Client)
            client.Incoming <-input
        }
    }
}

func ClientReader(client *Client){
    //make创建切片slice 长度2048 http://golang.org/doc/effective_go.html#allocation_make
    buffer :=make([]byte,2048)
    for {
        n, status := client.Read(buffer)
        if !status {
            break
        }

        if bytes.Equal(buffer,[]byte("/quit")){
            client.Close()
            break
        }
        Log("ClientReader received ",client.Name,"> ",string(buffer[:n]))
        send := client.Name+"> "+string(buffer[:n])
        client.Outgoing <- send
    }
    client.Outgoing <- client.Name + " has left chat"
    Log("ClientReader stopped for ", client.Name)
}

func ClientSender(client *Client){
    for {
        select {
            //select http://golang.org/doc/go_spec.html#Select_statements
        case buffer := <-client.Incoming:
            Log("ClientSender sending ",string(buffer), " to ",client.Name)
            client.Conn.Write([]byte(buffer))
        case <- client.Quit:
            Log("Client ",client.Name," quitting")
            client.Conn.Close()
            break
        }
    }
}

//该函数主要是接受新的连接和注册用户在client list
func ClientHandler(conn net.Conn,ch chan string,clientList *list.List){
        buffer := make([]byte,1024)
        bytesRead,error := conn.Read(buffer)
        if error != nil{
                Log("Client connection error: ",error)
        return
        }
        name := string(buffer[0:bytesRead])
//      newClient := &Client{name,make(chan string),ch,conn,make(chan bool),clientList}
//      初始化struct赋值的两种方法
        newClient := &Client{
        Name :name,
        Incoming : make(chan string),
        Outgoing : ch,
        Conn : conn,
        Quit : make(chan bool),
        ClientList : clientList,
    }
    //创建go的线程 使用Goroutine
        go ClientSender(newClient)
        go ClientReader(newClient)
        clientList.PushBack(*newClient)
        ch <-string(name + " has joined the chat ")
}

func main(){
        Log("Hello Server!")
        clientList := list.New()
    in := make (chan string)
    //创建一个管道 chan map 需要make creates slices, maps, and channels only
    go IOHandler(in,clientList)
    netListen,error := net.Listen("tcp",":9988")
    if error != nil {
        Log(error)
    }else{
        //defer函数退出时执行
        defer netListen.Close()
        for {
            Log("Waiting for clients")
            connection,error := netListen.Accept()
            if error != nil {
                Log("Client error: ",error)
            }else{
                go ClientHandler(connection,in,clientList)
            }
        }
    }
}

 

基本上使用这个服务,可以使用telnet IP 9988  多人进行聊天使用了

 

telnet 127.0.0.1 9988
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Name1
Name1
 has joined the chat 
Name1
> 
Jim
 has joined the chat Jim                                                                                  
>                                                                                                         
Jim                                                                                                       
> Hi!                                                                                                     
Jim                                                                                                       
> Nice to meeting you !                                                                                   
me Too                                                                                                    
Name1                                                                                                     
> me Too                                                                                                  
         

 

Client:

 

package main

import (
    "fmt";
    "net";
//    "log";
    "os";
    "bufio";
//    "strings";
    "time";
    "flag";
)

var running bool;  // global variable if client is running

var debug = flag.Bool("d", false, "set the debug modus( print informations )")

// func Log(v ...): loging. give log information if debug is true
//func Log(v ...) {
//    if *debug == true {
//        ret := fmt.Sprint(v);
//        log.Stdoutf("CLIENT: %s", ret);
//    }
//}
func Log(v ...interface{}){
        fmt.Println(v...)
}


// func test(): testing for error
func test(err os.Error, mesg string) {
    if err!=nil {
        Log("CLIENT: ERROR: ", mesg);
         os.Exit(-1);
    } else {
        Log("Ok: ", mesg);

    }
}

// read from connection and return true if ok
func readabc(con net.Conn) string{
    //var buf [4048]byte;
    buf := make([]byte,4096)
    _, err := con.Read(buf);
    if err!=nil {
        con.Close();
        running=false;
        return "Error in reading!";
    }
    fmt.Println();
    return string(buf);
}

// clientsender(): read from stdin and send it via network
func clientsender(cn net.Conn) {
    reader := bufio.NewReader(os.Stdin);
    for {
        fmt.Print("you> ");
        input, _ := reader.ReadBytes('\n');
        if string(input) == "/quit\n" {
            cn.Write([]byte("/quit"));
            running = false;
            break;
        }
        Log("clientsender(): send: ", string(input[0:len(input)-1]));
        cn.Write(input[0:len(input)-1]);
    }
}

// clientreceiver(): wait for input from network and print it out
func clientreceiver(cn net.Conn) {
    for running {
        fmt.Println(readabc(cn));
        fmt.Print("you> ");
    }
}

func main() {
    flag.Parse();
    running = true;
    Log("main(): start ");
    
    // connect
    destination := "127.0.0.1:9988";
    Log("main(): connecto to ", destination);
    cn, err := net.Dial("tcp", destination);
    test(err, "dialing");
    defer cn.Close();
    Log("main(): connected ");

    // get the user name
    fmt.Print("Please give you name: ");
    reader := bufio.NewReader(os.Stdin);
    name, _ := reader.ReadBytes('\n');

    //cn.Write(strings.Bytes("User: "));
    cn.Write(name[0:len(name)-1]);

    // start receiver and sender
    Log("main(): start receiver");
    go clientreceiver(cn);
    Log("main(): start sender");
    go clientsender(cn);
    
    // wait for quiting (/quit). run until running is true
    for ;running; {
        time.Sleep(1*1e9);
    }
    Log("main(): stoped");
}

gocode for golang 编程环境

作者:Ajian 发布时间:March 27, 2012 分类:Golang

前言:最近在学习go语言,我的编程环境是linux,使用vim,所以想整合下go的编程环境。在网上看到有一个gocode还不错可以自动补齐,相当的cool。

参考文章: http://www.mikespook.com/2011/03/gocode%E2%80%94%E2%80%94vim-%E5%92%8C-emacs-%E7%9A%84-golang-%E4%BB%A3%E7%A0%81%E8%87%AA%E5%8A%A8%E8%A1%A5%E5%85%A8/

gocode github地址: https://github.com/nsf/gocode

配置过程: 前提先要安装好go 配置好相关go的变量$GOROOT $GOBIN等
git clone git://github.com/nsf/gocode.git

cd gocode&&make install

我的是报错了make: *** No targets specified and no makefile found. Stop. 也不知道为什么 默认的clone出来没有makefile

只好从其它的分支里面弄出来一个

cd gocode&&git checkout go.r60&&go install

再配置vim

cd vim/&&./update.bash

确保 vim 启用了 filetype 插件,.vimrc 中应当有:filetype plugin on

基本上就没有问题了

附件带上我的vim配置文件和go vim环境自动安装脚本 可以 step by step 的协助集成 golang 相关脚本到 vim 中。(转自 http://www.mikespook.com/2011/09/%E4%B8%80%E4%B8%AA%E8%AE%BE%E7%BD%AE-golang-%E7%9A%84-vim-%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E7%9A%84%E8%84%9A%E6%9C%AC/)

下载地址:https://bitbucket.org/mikespook/learning_go_chinese/downloads/vim.sh

vimrc.txt vim配置文件(因为该blog上传指定了后缀才可以上传,所以下载保存为.vimrc就可以了)

效果图