GO WEB

1、第一个坑的就是,错误信息如下:

比较常见的错误“Connection reset by peer”,该错误和“Connection reset”是有区别的:

服务器返回了“RST”时,如果此时客户端正在从Socket套接字的输出流中数据则会提示Connection reset”;

服务器返回了“RST”时,如果此时客户端正在往Socket套接字的输入流中数据则会提示“Connection reset by peer”。

所以,很坑爹的一个就是,在连接TCP后,不能直接写数据,要让他睡睡。。。

下面是一个得到系统时间的server

也就是,我都还没第三次握手,我就send数据了。GG

https://my.oschina.net/xionghui/blog/508758

package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

func main() {
    server := ":7777"
    tcpAddr, err := net.ResolveTCPAddr("tcp4", server)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr) // pay atttion
    checkError(err)
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        fmt.Println(conn.RemoteAddr())
        go solve(conn)
    }
}

func solve(conn net.Conn) {
    defer conn.Close()
    dayTime := time.Now().String()
    conn.Write([]byte(dayTime))
    fmt.Println("teset")
}

func checkError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }
}
server
package main

import (
    "fmt"
    "io/ioutil"
    "net"
    "os"
    "time"
)

func main() {
    tcpAddr, errOne := net.ResolveTCPAddr("tcp", "127.0.0.1:7777")
    checkError(errOne)
    conn, errTwo := net.DialTCP("tcp", nil, tcpAddr)

    defer conn.Close()
    checkError(errTwo)

    time.Sleep(time.Second * 2) // 睡睡

    _, errThrid := conn.Write([]byte("hello"))
    checkError(errThrid)

    result, errOne := ioutil.ReadAll(conn)
    checkError(errOne)
    fmt.Println(string(result))

}

func checkError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }
}
client

 

2、socket的读取数据很bug啊,如果读取数据不合适,就会一直卡在那儿,很头痛。

TCP版本的聊天程序,用一个bufio.NewReader(TCPconn)来读取

package main

import (
    "bufio"
    "fmt"
    // "io/ioutil"
    "net"
    "os"
    "strings"
    "time"
)

var ch chan string = make(chan string, 10)

func main() {
    conn := newConnect()
    conn.SetNoDelay(false)
    fmt.Println("please enter your name")
    input := bufio.NewReader(os.Stdin)
    b, _, err := input.ReadLine()
    checkError(err)
    name := string(b)
    conn.Write([]byte("add " + name))
    // go func(conn net.Conn) {
    //     respond, err := ioutil.ReadAll(conn)
    //     checkError(err)
    //     if respond != "" {
    //         fmt.Println(string(respond))
    //     }
    // }(conn)

    //go getMessage(conn)
    go getMessage(conn)
    go showMessage()
    for {
        time.Sleep(time.Microsecond * 200)
        // helpUse()
        //conn = newConnect()
        request, err := input.ReadString('\n')
        checkError(err)

        _, err1 := conn.Write([]byte(request))
        checkError(err1)
    }
    defer conn.Close()
}

func getMessage(conn *net.TCPConn) {
    // var b []byte
    // read_len, err := conn.Read(b)
    // checkError(err)
    // return string(b[:read_len])

    // respond, err := ioutil.ReadAll(conn)
    // checkError(err)
    // return string(respond)
    //
    // fmt.Println("ff")
    // var b []byte
    // read_len, err := conn.Read(b)
    // fmt.Println("gg")
    // checkError(err)
    // fmt.Println(string(b[:read_len]))

    // fmt.Print("\n")
    r := bufio.NewReader(conn)
    for {
        str, err := r.ReadString('\n')
        checkError(err)
        res := strings.Split(str, "E")
        // ch <- "\n"
        for _, value := range res {
            if value == "\n" {
                // fmt.Print("\n")
                ch <- "\n"
                continue
            }
            // fmt.Println(value)
            ch <- value
        }
    }
}

func showMessage() {
    for {
        res := <-ch
        if res == "\n" {
            fmt.Println("")
        } else {
            fmt.Println(res)
        }
    }
}

func helpUse() {
    fmt.Println("------------------")
    fmt.Println("1、add user")
    fmt.Println("2、list all user online")
    fmt.Println("3、send message to xxx with text")
    fmt.Println("------------------")
}

func newConnect() *net.TCPConn {
    tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8282")
    checkError(err)
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    checkError(err)
    return conn
}

func checkError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }
}
client
package main

import (
    "fmt"
    "net"
    "os"
    "strings"
    "typeDefine"
)

var Muser typeDefine.TotalUser

func main() {
    Muser.OnlineUser = make([]*typeDefine.User, 0, 10)
    Muser.Mp = make(map[string]*net.TCPConn)
    service := ":8282"
    tcpAddr, err := net.ResolveTCPAddr("tcp", service)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr)
    checkError(err)

    for {
        conn, err := listener.AcceptTCP()
        fmt.Println("new user come")
        if err != nil {
            continue
        }
        go solve(conn)
    }
}

func solve(conn *net.TCPConn) {
    // conn.SetWriteBuffer(0)
    defer conn.Close()
    b := make([]byte, 512) //看看是否需要放入去,这个也不清零啊
    var name string
    for {

        readLen, err := conn.Read(b)
        if readLen == 0 {
            fmt.Println("bye~")
            return
        }
        checkError(err)
        request := strings.Split(string(b[:readLen]), " ")
        fmt.Println(request)
        // conn.Write([]byte("helloE"))
        // continue
        if request[0] == "ADD" || request[0] == "add" {
            if name != "" {
                continue
            }
            name = request[1]
            Muser.AddUser(request[1], conn)
            Muser.Mp[request[1]] = conn
        } else if request[0] == "LIST" || request[0] == "list" {
            Muser.ShowAllUserOnline(conn)
        } else {
            var tot string = name + " say: "
            for i := 1; i < len(request); i++ {
                tot += request[i]
                tot += " "
            }
            Muser.SendMessage(name, request[0], tot)
        }
    }

}

func checkError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }
}

// -----------------
server
package typeDefine

import (
    // "fmt"
    "net"
)

const MAXN = 10

type TotalUser struct {
    OnlineUser []*User
    Mp         map[string]*net.TCPConn
}

type User struct {
    Mes  chan string
    Name string
}

func (user *TotalUser) AddUser(name string, conn net.Conn) {
    if user.ExitUser(name, "") {
        conn.Write([]byte("unsuccessfully, the user " + name + " is already exits\n"))
        return
    }
    newUser := &User{nil, name}
    newUser.Mes = make(chan string, MAXN)
    user.OnlineUser = append(user.OnlineUser, newUser)
    conn.Write([]byte("Login successfully\n"))

    return
}

func (user *TotalUser) SendMessage(from string, to string, text string) {
    for i := range user.OnlineUser {
        onlineName := user.OnlineUser[i].Name
        if onlineName == from {
            continue
        }
        if onlineName == to {
            conn, _ := user.Mp[to]
            conn.Write([]byte(text + "\n"))
            return
        }
    }
}

func (user *TotalUser) ExitUser(findName string, expectName string) bool {
    for i := range user.OnlineUser {
        if user.OnlineUser[i].Name == expectName {
            continue
        }
        if user.OnlineUser[i].Name == findName {
            return true
        }
    }
    return false
}

func (user *TotalUser) ShowAllUserOnline(conn net.Conn) {
    for i := range user.OnlineUser {
        conn.Write([]byte(user.OnlineUser[i].Name + " onlineE"))
        //fmt.Println(user.OnlineUser[i].Name + " online")
    }
    conn.Write([]byte("\n"))
}
typeDefine

 

3、按任意键退出

 fmt.Scanln()

 

4、超时机制,查看routines是否超时

可以用 <- time.After(time.Second)

https://gobyexample.com/timeouts

 

5、基于udp的聊天程序,

用udpListener.ReadFromUDP即可

 

bug1、还是读入问题,读入一行可以使用

input := bufio.NewScanner(os.Stdin)

input.Scan()

input.Text()

 

bgu2、map不了指针??所以把*net.UdpConn转换成string来map了

 

基本思路是:

1️⃣、

知道服务器监听的端口,LocalHost + ServerPort

然后客户端也是要监听端口的(看起来和服务器一样),因为服务器也要发送消息给它,服务器要记录客户端监听了什么端口

一个端口不能两个东西同时监听,所以客户端的监听端口要rand出来。同时要告诉服务器我监听的端口,然后服务器就可能链接去你这里了。

 

2️⃣、

心跳包可以使用Ticker实现,但是我这里没实现

reference  http://blog.csdn.net/ssnian_/article/details/22949965

 

3️⃣、可以用default来断开链接,清除记录了的数据,因为本来是客户端等待数据进入,一开始是空stirng,或者是quit,然后关闭客户端后,就是相当于控制台没输入,然后就是一开始的stirng值,(客户端也会进入一次判断的) 就相当于quit。

package main

import (
    "errors"
    "fmt"
    "net"
    "os"
    "strings"
)

type User struct {
    Name     string
    userConn *net.UDPConn
    ChatConn *net.UDPConn
}

var ErrorCode = 1

//监听的端口 && 地址
var ServerPort = ":1212"
var LocalHost = "127.0.0.1"

//
var isOnline = make(map[string]*net.UDPConn)
var isUdpAddr = make(map[string]string)
var userSlice = make([]User, 0)

//心跳包检查,检测用户是否在线
func HeartCheck() {

}

// 得到连接
func getUdpConn(udpAddr string) (*net.UDPConn, error) {
    // fmt.Println("+++", udpAddr)
    // fmt.Println(isOnline["vimi"])
    // fmt.Println(isUdpAddr[udpAddr])
    if value, ok := isUdpAddr[udpAddr]; ok {
        if udpConn, ok := isOnline[value]; ok {
            return udpConn, nil
        }
    }
    fmt.Println("not found this user")
    return nil, errors.New("not found this user")
}

func UdpHandle(udpListener *net.UDPConn) {
    buff := make([]byte, 128)
    readLen, udpAddr, err := udpListener.ReadFromUDP(buff) //得到udp地址,就是那个用户的
    CheckError(err)

    // fmt.Printf("%+v  %d\n", udpAddr, readLen)

    go func() {
        if readLen > 0 {
            request := parseBuffer(buff, readLen)

            // 输出请求参数, debug
            fmt.Println("---------")
            for _, value := range request {
                fmt.Println(value)
            }
            fmt.Println("**********")

            switch request[0] {
            case "add":

                //找到用户监听的端口
                userUdpAddr, err := net.ResolveUDPAddr("udp", LocalHost+":"+request[2])
                CheckError(err)

                connClient, err := net.DialUDP("udp", nil, userUdpAddr) // 链接过去
                CheckError(err)

                isOnline[request[1]] = connClient
                isUdpAddr[udpAddr.String()] = request[1]
                fmt.Println(udpAddr, " 上线了")
                userSlice = append(userSlice, User{request[1], connClient, nil})

            case "show":
                connClient, err := getUdpConn(udpAddr.String())
                if err != nil {
                    break
                }
                for _, value := range userSlice { // 这个有bug,没删除元素,还没管理
                    sendMessage(value.Name+" online", connClient)
                }
            case "chat":
                connClient, err := getUdpConn(udpAddr.String())
                if err != nil {
                    break
                }
                _, ok := isOnline[request[1]]
                if !ok {
                    sendMessage("user "+request[1]+" off line", connClient)
                    break
                }
                context := ""
                for i := 2; i < len(request); i++ {
                    context += request[i]
                    context += " "
                }
                sendMessage(context, isOnline[request[1]])
            default:
                fmt.Println("bye~")
                name := isUdpAddr[udpAddr.String()]
                for i := 0; i < len(userSlice); i++ {
                    if userSlice[i].Name == name {
                        if len(userSlice) == 1 {
                            userSlice = make([]User, 0)
                        } else if i == 0 {
                            userSlice = userSlice[1:]
                        } else if i == len(userSlice)-1 {
                            userSlice = userSlice[:len(userSlice)-1]
                        } else {
                            userSlice = userSlice[:i]
                            userSlice = append(userSlice, userSlice[i+1:]...)
                        }
                        break
                    }
                }

                delete(isOnline, isUdpAddr[udpAddr.String()])
                delete(isUdpAddr, udpAddr.String())
            }
        } else {
            fmt.Println("bye bye")
            delete(isOnline, isUdpAddr[udpAddr.String()])
            delete(isUdpAddr, udpAddr.String())
        }
    }()
}

func sendMessage(context string, conn *net.UDPConn) {
    conn.Write([]byte(context))
}

// 把请求翻译出来
func parseBuffer(buff []byte, readLen int) []string {
    buffString := string(buff[:readLen])
    request := strings.Split(buffString, " ")
    return request
}

func main() {
    udpAddr, err := net.ResolveUDPAddr("udp", LocalHost+ServerPort)
    CheckError(err)
    udpListener, err := net.ListenUDP("udp", udpAddr)
    CheckError(err)
    defer udpListener.Close()
    go HeartCheck()
    fmt.Println("开始监听")

    for {
        UdpHandle(udpListener)
    }
}

func CheckError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(ErrorCode)
    }
}
server
package main

import (
    "bufio"
    "fmt"
    "math/rand"
    "net"
    "os"
    "strconv"
    "time"
)

var ErrorCode = 1

//监听的端口 && 地址
var ServerPort = ":1212"
var LocalHost = "127.0.0.1"

//判断是否已经使用该端口
var isUsePort = make(map[int]bool)

var op = map[string]string{
    "登录":     "add ",
    "显示在线人数": "show ",
    "聊天":     "chat ",
}

func CheckError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(ErrorCode)
    }
}

func getMessage(udpListener *net.UDPConn) {
    for {
        var buff = make([]byte, 128)
        readLen, _, err := udpListener.ReadFromUDP(buff)
        CheckError(err)
        if readLen > 0 {
            fmt.Println(string(buff[:readLen]))
        }
    }
}

func getUdpListener() (*net.UDPConn, int) {
    newSeed := rand.NewSource(int64(time.Now().Second()))
    newRand := rand.New(newSeed)

    for {
        randPort := newRand.Intn(3000) + 2000
        if _, ok := isUsePort[randPort]; ok {
            continue
        }
        //fmt.Println(randPort)
        isUsePort[randPort] = true

        udpAddr, err := net.ResolveUDPAddr("udp", LocalHost+":"+strconv.Itoa(randPort))
        CheckError(err)

        udpListener, err := net.ListenUDP("udp", udpAddr)
        CheckError(err)

        return udpListener, randPort
    }
}

func main() {
    var intServerPort int
    for i := 1; i < len(ServerPort); i++ {
        intServerPort = intServerPort*10 + int(ServerPort[i]-'0')
    }

    isUsePort[intServerPort] = true

    udpAddr, err := net.ResolveUDPAddr("udp", LocalHost+ServerPort)
    CheckError(err)

    udpConn, err := net.DialUDP("udp", nil, udpAddr)
    CheckError(err)

    udpListener, port := getUdpListener()

    defer udpConn.Close()
    defer udpListener.Close()

    name := ""
    fmt.Println("please enter your name")
    fmt.Scanf("%s", &name)
    udpConn.Write([]byte(op["登录"] + name + " " + strconv.Itoa(port)))

    go getMessage(udpListener)

    input := bufio.NewScanner(os.Stdin)

    for {
        opp := ""
        fmt.Scanf("%s", &opp)
        if opp == "show" {
            udpConn.Write([]byte(op["显示在线人数"]))
        } else if opp == "chat" {
            input.Scan()
            udpConn.Write([]byte(op["聊天"] + input.Text() + " text by " + name))
        } else {
            udpConn.Write([]byte("quit"))
            break
        }
    }
}
client

 

 

 

 

----------------------------------

 

go web like java forward 跳转

http.Redirect(w, r, "/show", http.StatusFound)

 

 

 

go use telegram(token改变了的)

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "net"
    "net/http"
    "net/url"
    "strconv"
    "time"

    ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
)

var config struct {
    server   string
    port     int
    password string
    method   string
}

func handleError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}
func HTTPClientBySocks5(uri string) *http.Client {
    parsedURL, err := url.Parse(uri)
    handleError(err)
    host, _, err := net.SplitHostPort(parsedURL.Host)
    if err != nil {
        if parsedURL.Scheme == "https" {
            host = net.JoinHostPort(parsedURL.Host, "443")
        } else {
            host = net.JoinHostPort(parsedURL.Host, "80")
        }
    } else {
        host = parsedURL.Host
    }
    rawAddr, err := ss.RawAddr(host)
    handleError(err)
    serverAddr := net.JoinHostPort(config.server, strconv.Itoa(config.port))
    cipher, err := ss.NewCipher(config.method, config.password)
    handleError(err)
    dailFunc := func(network, addr string) (net.Conn, error) {
        return ss.DialWithRawAddr(rawAddr, serverAddr, cipher.Copy())
    }
    //dailContext := func(ctx context.Context, network, addr string) (net.Conn, error) {}
    tr := &http.Transport{
        MaxIdleConns:          100,
        IdleConnTimeout:       90 * time.Second,
        TLSHandshakeTimeout:   10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    }
    tr.Dial = dailFunc
    return &http.Client{Transport: tr}
}
func Get(uri string) (resp *http.Response, err error) {
    client := HTTPClientBySocks5(uri)
    return client.Get(uri)
}
func Post(uri string, contentType string, body io.Reader) (resp *http.Response, err error) {
    client := HTTPClientBySocks5(uri)
    return client.Post(uri, contentType, body)
}
func PostForm(uri string, data url.Values) (resp *http.Response, err error) {
    client := HTTPClientBySocks5(uri)
    return client.PostForm(uri, data)
}
func Head(uri string) (resp *http.Response, err error) {
    client := HTTPClientBySocks5(uri)
    return client.Head(uri)
}

type two struct {
    Text string `json:"text"`
    Url  string `json:"url"`
}

type one struct {
    InlineKeyBodard [][]*two `json:"inline_keyboard"`
}

type Message struct {
    ChatID      string `json:"chat_id"`
    Text        string `json:"text"`
    ReplyMarkup *one   `json:"reply_markup"`
    ParseMode   string `json:"parse_mode"`
}

func testMe() {
    item := &two{"go", "www.google.com"}
    temp := &one{[][]*two{}}

    t := []*two{}
    t = append(t, item)
    t = append(t, item)
    temp.InlineKeyBodard = append(temp.InlineKeyBodard, t)

    msg := &Message{
        ChatID:      "-264517585",
        Text:        "[test](www.baidu.com)",
        ReplyMarkup: temp,
        ParseMode:   "markdown",
    }
    b, _ := json.Marshal(msg)
    re := bytes.NewBuffer(b)
    // fmt.Println(msg)

    fmt.Println(string(b))

    Post("https://api.telegram.org/bot516690928:AAH4l2EyC8YAFalLut6oWv-1BrqgoAkfo/sendMessage", "application/json", re)
}

func main() {
    // for testing
    config.method = "aes-256-cfb" // default method
    config.password = "stupidone"
    config.port = 1080 // your port
    config.server = "95.163.202.160"
    testMe()

    //     var uri string = "https://api.telegram.org/bot516690928:AAH4EyC8YAFalLut6ZMoWv-1BrqgoAkfo/getMe"
    //     resp, err := Get(uri)
    //     handleError(err)
    //     defer resp.Body.Close()
    //     body, err := ioutil.ReadAll(resp.Body)
    //     handleError(err)
    //     fmt.Println(string(body))
}
View Code

这里想记录的是json出一个button是怎样做的,对应下面的

http://donggu.me/2018/03/15/Telegram%E5%BC%80%E5%8F%91%E5%B0%8F%E8%AE%B0/

 

golang http.get走本地代理

golang走代理

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "time"

    "golang.org/x/net/proxy"
)

func main() {

    go func() {
        select {
        case <-time.After(time.Second * 10):
            break
        }
        os.Exit(1)
    }()

    dialSocksProxy, err := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, proxy.Direct)

    if err != nil {
        fmt.Println("Error connecting to proxy:", err)
        return
    }
    tr := &http.Transport{Dial: dialSocksProxy.Dial}
    // Create client
    myClient := &http.Client{
        Transport: tr,
    }
    response, err := myClient.Get("https://api.telegram.org/bot516690928:AAH4EyC8YAFalLut6ZMoWv-1BrqgoAkfo/getMe")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer response.Body.Close()
    var by []byte
    by, _ = ioutil.ReadAll(response.Body)
    fmt.Println(string(by))
}
View Code

 

 

--------------------------------------------------------------------------------------------------------------------------------------------

golang写后台,java写client

package main

import (
    "fmt"
    "net"

    "github.com/sirupsen/logrus"
)

const (
    addr    = ":7070"
    netWork = "tcp"
)

func checkErr(err error) {
    if err != nil {
        logrus.Error(err)
    }
}

func main() {
    tcpAddr, err := net.ResolveTCPAddr(netWork, addr)
    checkErr(err)
    s, err := net.ListenTCP(netWork, tcpAddr)
    checkErr(err)

    for {
        fmt.Println("new")
        conn, err := s.AcceptTCP()
        if err != nil {
            logrus.Error(err)
            continue
        }
        go solve(conn)
    }
}

func solve(conn *net.TCPConn) {
    defer conn.Close()
    b := make([]byte, 512)
    for {
        readLen, err := conn.Read(b)
        if readLen == 0 {
            fmt.Println("bye~")
            return
        }
        if err != nil {
            logrus.Error(err)
            continue
        }
        fmt.Println(string(b))
        _, err = conn.Write([]byte("Send OK\n"))
        // time.Sleep(time.Second)
        checkErr(err)
    }
}
go-server
package main

import (
    "bufio"
    "fmt"
    "net"

    "github.com/sirupsen/logrus"
)

const (
    addr    = "47.106.195.179:7070"
    netWork = "tcp"
)

func checkErr(err error) {
    if err != nil {
        logrus.Error(err)
    }
}

func main() {
    tcpAddr, err := net.ResolveTCPAddr(netWork, addr)
    checkErr(err)

    conn, err := net.DialTCP(netWork, nil, tcpAddr)
    checkErr(err)

    _, err = conn.Write([]byte("This is my homework of network ,I am happy!"))
    checkErr(err)

    r := bufio.NewReader(conn)
    b, _, err := r.ReadLine()
    checkErr(err)
    fmt.Println(string(b))
}
go-client
package room.vimi.crawler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class App {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket socket = new Socket("47.106.195.179", 7070);
        
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        BufferedReader buffer_reader = new BufferedReader(reader);
        
        PrintWriter writer = new PrintWriter(socket.getOutputStream());
        
        String one = "hello";
        writer.println(one);
        writer.flush();
        
        String res = buffer_reader.readLine();
        System.out.println(res);
    }
}
java-client

 

posted on 2018-02-02 18:59  stupid_one  阅读(411)  评论(0编辑  收藏  举报

导航