Golang Socket Server

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Main.go the code is separated from the project and then run by itself)

package mainimport  ("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 stdoutlogfile, 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&nbsP;| log. Lshortfile)//set logfile stdout end//start listenlistenerr := startlisten (*Port) If listenerr != nil {log. Fatalf ("server abort! cause:%v \n",  listenerr)}}

Two, Listener.go

package mainimport  ("Code.google.com/p/go-uuid/uuid" "Errors" "FMT" "Gocs/consistent" "Log" "NET" "Sync" " Time ") const  (Connectionmax = 100 //cs max connect)//conn pool infovar   (Poollock sync. Rwmutexpoolcli  [connectionmax]*cliinfo)//web user infotype userinfo struct  {WS_ID       intWS_Name      Stringservicename string}//cli infotype cliinfo struct {assignid   int             //cs assign IDConn        net. conn       // the tcp/ip connectin to the  Player. Conntime   time. time      //Connection Time verifykey  string          //Connection Verification Keyconnverify bool           //whether to verify servertype int32           //server type (1DB server, 2WEB server) nodestat   int32           //Server Current status (0, downtime, 1, normal, 2, data import; 3, preparation; 4) address  in the data migration    string         //Service Address port        int            // Service Port backupser  map[string]int //Backup Server list map (ip:port) sync. Rwmutex}type hashpool struct {version  intcircle   map[uint32]string  //hash Circle node Distribution replicas map[string]int    //hash Ring node range}var serhashpool * Consistent. Consistent = consistent. New ()// client disconnectfunc  (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 {//off-line processing If ok := cli.removedbs ();  ok {poolcli[clientid]  = nil}} else {}}//listen handlefunc  (cli *cliinfo)  listenhandle ( Clientid int)  {headbuff := make ([]byte, 12)  // set read stream  sizedefer 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 verifycli. Conn.setdeadline (time. Now (). ADD (time. Duration (Ten)  * time. Second)) forcontrol := truefor forcontrol {var headnum intfor headnum  < cap (Headbuff)  {readheadnum, readheaderr := cli. Conn.read (headbuff[headnum:]) if readheaderr != nil {log. Println ("Errhead:", &nbsP;readheaderr) forcontrol = falsebreak}headnum += readheadnum}if headnum ==  Cap (Headbuff)  {//pack head handlepackhead := packheadanalysis (HeadBuff) bodyBuff  : = make ([]byte, packhead.packlen) Var bodynum intfor bodynum < cap ( Bodybuff)  {readbodynum, readbodyerr := cli. Conn.read (bodybuff[bodynum:]) if readbodyerr != nil {log. Println ("Errbody:",  readbodyerr) forcontrol = falsebreak}bodynum += readbodynum}if  bodynum == int (Packhead.packlen)  {//pack body handlecli.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 connfunc  Newconnection_cs (conn net. Conn)   (ok bool, index Int, info *cliinfo)  {poollock.lock () Defer poollock.unlock ()//assign id for  Clientvar i intfor i = 0; i < connectionmax; i++ {if  poolCli[i] == nil {break}}//Too many connectionsif i >  Connectionmax {log. Printf ("too many connections! active denial %s\n",  conn. Remoteaddr (). String ()) Conn. Close () return false, 0, nil}//create client base infocli := new ( Cliinfo) Cli.conn = conncli.conntime = time. Now () Cli.verifykey = uuid. New () cli.backupser = make (map[string]int)//update pool infopoolcli[i] =  Clilog.println ("Cli id assign ok:",  i) return true, i, cli}//start  Listensfunc startlisten (addr string)  error {listener, err := net. Listen ("TCP", &NBSP;ADDR) if err != nil {return err}// if errors accept arrive 100 . listener stop.for failures := 0; failures < 100; {conn,  Listenerr := listener. Accept () If listenerr != nil {log. Printf ("number:%d,failed listening:%v\n",  failures, listenerr) Failures++}if ok, index , &NBSP;CLI&NBSP;:=&NBSP;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 ")}

Three, the principle

A new connection is established. Generate a new gorouting to process the client.

A client comes in first assigning a unique ID and initializing the client's basic information (see: Newconnection_cs method), generating a new gorouting to handle the client.

If the server reaches the set connection limit, the client is discarded.

After the client connection (Assignment ID) is normal, it waits 10 seconds for the client to be authenticated and the client connection will be disconnected (see Cli.Conn.SetDeadline in Listenhandle).

After successful verification, the open-connect and User data processing: The first 4 bytes for the packet type, 4-12 bytes for the packet length, first received enough 12 bytes after the Baotou parsing (if not enough 12 bytes will wait until enough 12 bytes), parsing out 4-12 bytes to get the length of the entire package read (If not enough will wait until enough length of the bag)

After the whole packet has been read, the packet is processed according to the type of 0-4 bytes.

Four, the server connection error reached 100 after the operation will be terminated

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.