///============================ ///消费者 获取图片 func getFile(session *link.Session, req map[string]string) error { seq := req["seq"] //死等 vf := QueueInstance.DeChan() if vf == nil { ULogger.Error("getfile time out,sessioninfo is %s", session.State.(*User).Id) ret := map[string]string{ "action": "res_getfile", "seq": seq, } by, _ := json.Marshal(ret) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) return nil } vf.C = session vf.CInfo = session.State.(*User).Id vf.Status = 2 vf.CGetUnix = time.Now().Unix() ret := map[string]string{ "action": "res_getfile", "seq": seq, "id": vf.Id, "file": vf.File, } by, _ := json.Marshal(ret) VFMapInstance.Update("c_getfile", vf) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) return nil }
// This is an echo server demo work with the echo_client. // usage: // go run echo_server/main.go func main() { common.ULogger.Info("stat chat at ", 10010) //flag.Parse() link.DefaultConnBufferSize = *buffersize link.DefaultProtocol = http.HttpPacket server, err := link.Listen("tcp", "0.0.0.0:10010") if err != nil { panic(err) } //server.Protocol() common.ULogger.Info("server start:", server.Listener().Addr().String()) server.Serve(func(session *link.Session) { common.ULogger.Info("client", session.Conn().RemoteAddr().String(), "in") SessionInfo := &proxy.Session_Info{} session.State = SessionInfo session.Process(func(msg *link.InBuffer) error { common.ULogger.Info("receive request ", session.Conn().RemoteAddr().String(), ":", string(msg.Data)) req, _ := http.Parse(msg.Data) req_CallId, ok1 := req.HEADER["CallId"] resp, other := proxy.ProcessRequest(req, SessionInfo) _ = other _, ok2 := resp.HEADER["CallId"] // add callid if ok1 && !ok2 { resp.AddResponseHeader("CallId", req_CallId) } //str := "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n" common.ULogger.Info("send response ", session.Conn().RemoteAddr().String(), ":", string(resp.ToByte())) if SessionInfo.Data_Ex != "" { session.Send(link.Bytes(resp.ToByte())) return session.Send(link.String(SessionInfo.Data_Ex)) } else { return session.Send(link.Bytes(resp.ToByte())) } }) common.ULogger.Info("client", session.Conn().RemoteAddr().String(), "close") }) }
//c端回答的问题 func answer(session *link.Session, req map[string]string) error { id := req["id"] answer := req["answer"] vf := VFMapInstance.Get(id) if vf == nil { ULogger.Errorf("answer,verifyobj not found,may be timeout%v\n") Exec(`update exam set f_status=8,answer_time=now(),answer=? where file_id=?`, answer, id) return nil } vf.Answer = answer vf.Status = 3 vf.CInfo = session.State.(*User).Id //c回答了问题 VFMapInstance.Update("c_answer", vf) if vf.P != nil && !vf.P.IsClosed() { //相当于putfile 的应答 ret := map[string]string{ "action": "res_putfile", "seq": vf.Seq, "id": vf.Id, "answer": answer, } by, _ := json.Marshal(ret) vf.P.Send(link.Bytes(by)) ULogger.Info("send to client", vf.P.Conn().RemoteAddr().String(), "say:", string(by)) //给P投递了消息 VFMapInstance.Update("p_fileanswer", vf) } else { ULogger.Info("p have closed") VFMapInstance.Update("p_close", vf) } return nil }
func Test_Simple(t *testing.T) { backend, err := StartEchoBackend() unitest.NotError(t, err) gateway := StartTestGateway(t, backend.Listener().Addr().String()) gatewayAddr := gateway.server.Listener().Addr().String() client, err := link.Connect("tcp://"+gatewayAddr, link.Packet(link.Uint16BE), link.Bytes()) unitest.NotError(t, err) for i := 0; i < 10000; i++ { msg1 := RandBytes(1024) err1 := client.Send(msg1) unitest.NotError(t, err1) var msg2 []byte err2 := client.Receive(&msg2) unitest.NotError(t, err2) if bytes.Equal(msg1, msg2) == false { t.Log(i, msg1, msg2) t.Fail() } unitest.Pass(t, bytes.Equal(msg1, msg2)) } client.Close() gateway.Stop() backend.Stop() time.Sleep(time.Second * 2) MakeSureSessionGoroutineExit(t) }
func init() { go func() { t1 := time.NewTimer(time.Second * 60) t2 := time.NewTimer(time.Second * 90) for { select { case <-t1.C: nowUnix := time.Now().Unix() for k, v := range VFMapInstance.innerMap { //p 端超时 if v.PPutUnix+900 < nowUnix { ULogger.Info("%s file timeout", v.Id) delete(VFMapInstance.innerMap, k) if v.P != nil && v.P.IsClosed() { v.P.Close() } } //被c 端获取且超时 if v.Status == 2 && (v.CGetUnix+300) < nowUnix { ULogger.Info("%s recycle", v.Id) VFMapInstance.Update("recycle", v) delete(VFMapInstance.innerMap, k) vf := &VerifyObj{Id: getId(), P: v.P, C: nil, FileId: v.FileId, File: v.File, Status: 1, Result: "0", Seq: v.Seq, PPutUnix: v.PPutUnix} QueueInstance.Enqueue(vf) VFMapInstance.Put(vf) ULogger.Infof("recycle putfile 进队列 %v\n", vf) putFile(v.P, map[string]string{"file": v.File, "seq": v.Seq, "action": "putfile"}) } } t1.Reset(time.Second * 60) case <-t2.C: //fmt.Println("ss") stat := map[string]string{"action": "stat"} //TCServer. for k, v := range VFMapInstance.c_sessions { if v == nil || v.State == nil { delete(VFMapInstance.c_sessions, k) } u := v.State.(*User) query := `select count(*) from exam where c_userid=? and c_getfile_time > ? and answer is not null` //c端回答的问题总数 canswer := QueryInt(query, u.Id, u.WorkTime) query1 := `select count(*) from exam where c_userid=? and c_getfile_time > ? and answer is not null and answer_result=1` canswerrigth := QueryInt(query1, u.Id, u.WorkTime) waitcount := QueueInstance.len() clientcount := len(VFMapInstance.c_sessions) stat["finishcount"] = strconv.Itoa(canswer) stat["rightcount"] = strconv.Itoa(canswerrigth) stat["waitcount"] = strconv.Itoa(waitcount) stat["clientcount"] = strconv.Itoa(clientcount) by, _ := json.Marshal(stat) v.Send(link.Bytes(by)) ULogger.Info("send to client", v.Conn().RemoteAddr().String(), "say:", string(by)) } t2.Reset(time.Second * 90) } } }() }
func NewFrontend(listener link.IPacketListener, handshaker ClientHandshaker) *Frontend { front := &Frontend{ server: link.NewServer(listener, link.Bytes()), links: make(map[uint64]*frontendLink), handshaker: handshaker, } go front.loop() return front }
///c端开始答题 func cStart(session *link.Session, req map[string]string) error { userid := req["userid"] password := req["password"] seq := req["seq"] ULogger.Infof("user %s start answer", userid) ret := map[string]string{ "action": "res_cstart", "seq": seq, "result": "0", } if session.State != nil && session.State.(*User).UserType == "C" { ULogger.Error("have logined ", userid) session.Close() } if b := Login(userid, password); !b { ULogger.Errorf("cstart failed ,userid is %s password is %s", userid, password) by, _ := json.Marshal(ret) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) session.Close() return nil } else { user := &User{UserType: "C", Id: userid, WorkTime: time.Now().Format("2006-01-02 15:04:05")} session.State = user ret["result"] = "1" by, _ := json.Marshal(ret) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) //c端开始答题 Exec(`insert into user_activities(user_id,active_time,active_type,user_type,other_info) values(?,now(),'begin','customer',?)`, userid, session.Conn().RemoteAddr().String()) VFMapInstance.AddSession(session) } return nil }
func client(initWait *sync.WaitGroup, conn *CountConn, startChan chan int, timeout time.Time, msg []byte) { pConn, _ := link.Packet(link.Uint16BE).NewClientConn(conn) client := link.NewSession(pConn, link.Bytes()) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() initWait.Done() <-startChan for { outMsg := msg if *randsize { outMsg = make([]byte, rand.Intn(*messageSize)) } if err := client.Send(outMsg); err != nil { if timeout.After(time.Now()) { println("send error:", err.Error()) } break } atomic.AddUint32(&conn.SendCount, 1) } }() wg.Add(1) go func() { defer wg.Done() initWait.Done() <-startChan var inMsg []byte for { if err := client.Receive(&inMsg); err != nil { if timeout.After(time.Now()) { println("recv error:", err.Error()) } break } atomic.AddUint32(&conn.RecvCount, 1) } }() wg.Wait() }
func StartEchoBackend() (*link.Server, error) { backend, err := link.Serve("tcp://0.0.0.0:0", NewBackend(), link.Bytes()) if err != nil { return nil, err } go backend.Loop(func(session *link.Session) { var msg []byte for { if err := session.Receive(&msg); err != nil { break } if err := session.Send(msg); err != nil { break } } }) return backend, nil }
func main() { var addr string flag.StringVar(&addr, "addr", ":10010", "echo server address") flag.Parse() server, err := link.Serve("tcp", addr, link.Bytes(link.Uint16BE)) if err != nil { panic(err) } println("server start:", server.Listener().Addr().String()) for { session, err := server.Accept() if err != nil { break } go io.Copy(session.Conn(), session.Conn()) } }
func Test_Broadcast(t *testing.T) { var ( clientNum = 20 packetNum = 2000 channel = NewChannel(link.Bytes()) broadcastMsg []byte broadcastWait sync.WaitGroup clientWait sync.WaitGroup ) backend, err := link.Serve("tcp://0.0.0.0:0", NewBackend(), link.Bytes()) unitest.NotError(t, err) go backend.Loop(func(session *link.Session) { channel.Join(session) clientWait.Done() for { var msg []byte if err := session.Receive(&msg); err != nil { break } unitest.Pass(t, bytes.Equal(msg, broadcastMsg)) broadcastWait.Done() } }) clientWait.Add(clientNum) go func() { clientWait.Wait() for i := 0; i < packetNum; i++ { broadcastMsg = RandBytes(1024) channel.Broadcast(broadcastMsg) broadcastWait.Add(clientNum) broadcastWait.Wait() } }() gateway := StartTestGateway(t, backend.Listener().Addr().String()) gatewayAddr := gateway.server.Listener().Addr().String() var wg sync.WaitGroup for i := 0; i < clientNum; i++ { wg.Add(1) go func() { defer wg.Done() client, err := link.Connect("tcp://"+gatewayAddr, link.Packet(link.Uint16BE), link.Bytes()) unitest.NotError(t, err) for j := 0; j < packetNum; j++ { var msg []byte err := client.Receive(&msg) unitest.NotError(t, err) err = client.Send(msg) unitest.NotError(t, err) } client.Close() }() } wg.Wait() gateway.Stop() backend.Stop() time.Sleep(time.Second * 2) MakeSureSessionGoroutineExit(t) }