golang连接java的socket_golang socket服务器

一、main.go该代码从项目中分离出来,自行修改后再运行)

package main

import (

"flag"

"fmt"

"log"

"os"

"runtime"

)

var (

Port           = flag.String("i", ":12345", "IP port to listen on")

logFileName    = flag.String("log", "cServer.log", "Log file name")

configFileName = flag.String("configfile", "config.ini", "General configuration file")

)

var (

configFile = flag.String("configfile", "config.ini", "General configuration file")

)

func main() {

runtime.GOMAXPROCS(runtime.NumCPU())

flag.Parse()

//set logfile Stdout

logFile, logErr := os.OpenFile(*logFileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)

if logErr != nil {

fmt.Println("Fail to find", *logFile, "cServer start Failed")

os.Exit(1)

}

log.SetOutput(logFile)

log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

//set logfile Stdout End

//start listen

listenErr := StartListen(*Port)

if listenErr != nil {

log.Fatalf("Server abort! Cause:%v \n", listenErr)

}

}

二、listener.go该代码从项目中分离出来,自行修改后再运行)

package main

import (

"code.google.com/p/go-uuid/uuid"

"errors"

"fmt"

"goCS/consistent"

"log"

"net"

"sync"

"time"

)

const (

ConnectionMax = 100 //CS max connect

)

//conn Pool info

var (

poolLock sync.RWMutex

poolCli  [ConnectionMax]*CliInfo

)

//Web user info

type UserInfo struct {

WS_ID       int

WS_Name     string

ServiceName string

}

//Cli info

type CliInfo struct {

AssignID   int            //cs assign ID

Conn       net.Conn       // The TCP/IP connectin to the player.

ConnTime   time.Time      //连接时间

VerifyKey  string         //连接验证KEY

ConnVerify bool           //是否验证

ServerType int32          //服务器类型(1DB服务器,2WEB服务器)

NodeStat   int32          //服务器当前状态(0、宕机;1、正常;2、数据导入中;3、准备中;4、数据迁出中

Address    string         //服务地址

Port       int            //服务端口

BackupSer  map[string]int //备份服务器列表map(ip:port)

sync.RWMutex

}

type hashPool struct {

Version  int

Circle   map[uint32]string //hash圈节点分布

Replicas map[string]int    //hash圈节点范围

}

var SerHashPool *consistent.Consistent = consistent.New()

// Client disconnect

func (cli *CliInfo) disconnect(clientID int) {

poolLock.Lock()

defer poolLock.Unlock()

cli.Conn.Close()

log.Printf("Client: %s quit\n", cli.VerifyKey)

if cli.ServerType == 1 {

//掉线处理

if ok := cli.removeDBS(); ok {

poolCli[clientID] = nil

}

} else {

}

}

//listen handle

func (cli *CliInfo) listenHandle(clientID int) {

headBuff := make([]byte, 12) // set read stream size

defer cli.Conn.Close()

//send verify Key:

b := []byte(cli.VerifyKey)

cli.Conn.Write(b)

// fmt.Println("cli-IP:", cli.Conn.RemoteAddr().String())

//await 10 second verify

cli.Conn.SetDeadline(time.Now().Add(time.Duration(10) * time.Second))

forControl := true

for forControl {

var headNum int

for headNum 

readHeadNum, readHeadErr := cli.Conn.Read(headBuff[headNum:])

if readHeadErr != nil {

log.Println("errHead:", readHeadErr)

forControl = false

break

}

headNum += readHeadNum

}

if headNum == cap(headBuff) {

//pack head Handle

packHead := packHeadAnalysis(headBuff)

bodyBuff := make([]byte, packHead.PackLen)

var bodyNum int

for bodyNum 

readBodyNum, readBodyErr := cli.Conn.Read(bodyBuff[bodyNum:])

if readBodyErr != nil {

log.Println("errBody:", readBodyErr)

forControl = false

break

}

bodyNum += readBodyNum

}

if bodyNum == int(packHead.PackLen) {

//pack body Handle

cli.packBodyAnalysis(clientID, packHead, bodyBuff)

// fmt.Printf("packType:%d;packOther:%d;packLen:%d\n", packHead.PackType, packHead.PackOther, packHead.PackLen)

}

}

}

cli.disconnect(clientID)

}

//Check or assign new conn

func NewConnection_CS(conn net.Conn) (ok bool, index int, info *CliInfo) {

poolLock.Lock()

defer poolLock.Unlock()

//Assign ID for client

var i int

for i = 0; i 

if poolCli[i] == nil {

break

}

}

//Too many connections

if i > ConnectionMax {

log.Printf("Too many connections! Active Denial %s\n", conn.RemoteAddr().String())

conn.Close()

return false, 0, nil

}

//Create client base info

Cli := new(CliInfo)

Cli.Conn = conn

Cli.ConnTime = time.Now()

Cli.VerifyKey = uuid.New()

Cli.BackupSer = make(map[string]int)

//Update Pool info

poolCli[i] = Cli

log.Println("Cli ID assign ok:", i)

return true, i, Cli

}

//start listens

func StartListen(addr string) error {

listener, err := net.Listen("tcp", addr)

if err != nil {

return err

}

// if Errors accept arrive 100 .listener stop.

for failures := 0; failures 

conn, listenErr := listener.Accept()

if listenErr != nil {

log.Printf("number:%d,failed listening:%v\n", failures, listenErr)

failures++

}

if ok, index, Cli := NewConnection_CS(conn); ok {

// A new connection is established. Spawn a new gorouting to handle that Client.

go Cli.listenHandle(index)

}

}

return errors.New("Too many listener.Accept() errors,listener stop")

}

三、原理

一个新的连接建立。产生一个新的gorouting来处理客户端。

一个客户端进来首先分配一个唯一ID,并初始化该客户端的基本信息(见:NewConnection_CS方法),产生一个新的gorouting来处理客户端。

如果服务器达到设定的连接上限,将抛弃该客户端。

客户端连接(分配ID)正常后,将等待10秒来给客户端进行验证超期将断开该客户端连接(见:listenHandle中的cli.Conn.SetDeadline)。

验证成功后,开接与用户数据进行分析处理:接收原理为:前4字节为包类型,4-12字节为包长,首先接收够12字节后进行包头解析(如不够12字节将进行等待直到够12字节),解析出4-12字节来得到整个包体的长度进行读取(如不够将等待直到够包体长度)

整包读取完后,根据0-4字节判断包的类型进行包的处理。

四、服务器连接出错达到100条后将终止运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值