# 網路編程基本技術 ![](https://hackmd.io/_uploads/HkcSl3ob6.png) https://www.youtube.com/watch?v=P6SZLcGE4us&ab_channel=ByteByteGo ## TCP IP UDP https://www.youtube.com/watch?v=Iuvjwrm_O5g https://blog.csdn.net/freekiteyu/article/details/72236734 ![](https://i.imgur.com/asiBMFt.png) ## ip ip是osi 會自動帶入的 然後lb例如nginx自動帶入到 x-forward 所以我們要抓第一個 ``` func ParseIP(ctx context.Context, positionWithZeroBase int) (net.IP, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, errors.New("ParseIP: failed to read metadata") } ips, err := getIPStringFromMetadata(md, positionWithZeroBase) if err != nil { return nil, err } log.Debug("ParseIP from md: ", ips) ipValue, err := getIPValue(ctx, ips) if err != nil { return nil, err } ip := net.ParseIP(ipValue) if ip == nil { return nil, errors.New("ParseIP: invalid IP address") } return ip, nil } func getIPStringFromMetadata(md metadata.MD, positionWithZeroBase int) ([]string, error) { check := md.Get("x-forwarded-for") if len(check) < 1 { return []string{}, errors.New("ParseIP: no IP found") } ips := strings.Split(check[0], ",") if len(ips)-1 < positionWithZeroBase { return []string{}, errors.New("ParseIP: no IP in specific position") } return ips, nil } func getIPValue(ctx context.Context, ips []string) (string, error) { for i, ip := range ips { isGoogle, err := IsGoogleLoadBalancerIP(ip) if err != nil { return "", fmt.Errorf("ParseIP: IsGoogleLoadBalancerIP: %v: %v", ip, err) } if isGoogle { if i > 0 { return strings.Split(ips[i-1], ":")[0], nil } break } } peerMd, ok := peer.FromContext(ctx) if !ok { return "", errors.New("ParseIP: failed to read peer data") } return strings.Split(peerMd.Addr.String(), ":")[0], nil } ``` 抓google白名單 ``` package gocom import ( "errors" "fmt" "net" "regexp" "strings" "sync" "github.com/lctech-tw/face-front-api/pkg/iprange" ) var gcpTxtRecordAll []string var gcpTxtRecordOnce sync.Once var gcpIpRangeAll []string var gcpIsDeveloperTriggered bool // ErrGcpMustLookup usually panic to alert developers to lookup and make sure the system is secured by correct Google IP Range. var ErrGcpMustLookup = errors.New("Developers are responsible to call LookupGoogleIPs prior to Application execution") // LookupGoogleIPs loads IP range from _cloud-eoips.googleusercontent.com and store them in memory to prevent Ddos of dns lookup. // According to https://cloud.google.com/load-balancing/docs/negs/internet-neg-concepts#authenticating_requests, // https://cloud.google.com/load-balancing/docs/https#x-forwarded-for_header func LookupGoogleIPs(moreIpRange []string) (err error) { gcpTxtRecordOnce.Do(func() { gcpTxtRecordAll, err = net.LookupTXT("_cloud-eoips.googleusercontent.com") if err != nil { err = fmt.Errorf("LookupGoogleIPs: %v", err) return } for _, txt := range gcpTxtRecordAll { finder, errRegex := regexp.Compile(`ip4:([^ ]+)`) if err != nil { err = fmt.Errorf("failed to detect GCP IP: %v", errRegex) return } for _, ipCIDR := range finder.FindAllStringSubmatch(txt, -1) { gcpIpRangeAll = append(gcpIpRangeAll, ipCIDR[1]) } } // according to https://cloud.google.com/load-balancing/docs/https#x-forwarded-for_header gcpIpRangeAll = append(gcpIpRangeAll, "130.211.0.0/22", "35.191.0.0/16") if len(moreIpRange) > 0 { gcpIpRangeAll = append(gcpIpRangeAll, moreIpRange...) } gcpIsDeveloperTriggered = true }) return } func GetGoogleIpRangeAll() []string { if gcpIsDeveloperTriggered == false { panic(ErrGcpMustLookup) } return gcpIpRangeAll } func IsGoogleLoadBalancerIP(ipStr string) (result bool, err error) { if gcpIsDeveloperTriggered == false { err = ErrGcpMustLookup return } ipStr = strings.TrimSpace(ipStr) ipAddr := net.IP{} err = ipAddr.UnmarshalText([]byte(ipStr)) if err != nil { err = fmt.Errorf("IsGoogleLoadBalancerIP:invalid:%v", err) return } for _, ipr := range GetGoogleIpRangeAll() { r, errRange := iprange.ParseRange(ipr) if errRange != nil { err = fmt.Errorf(":%v", errRange) return } if r.Contains(ipAddr) { result = true return } } return } ``` ## data corruption 預防外部重複呼叫造成的數據破壞 在設計API時,特別是那些修改數據的API(例如命令或寫操作),确保操作的幂等性是非常重要的。幂等性指的是多次執行同一操作的效果與執行一次相同。這可以預防由於用戶操作不當或重試機制引起的重複調用導致的數據破壞。實現幂等性的方法可能包括: 使用唯一的事務ID來檢測和忽略重複的請求。 確保操作的重複執行不會更改系統狀態。 ## 服務器推送、在線遊戲和電子郵件背後的網絡協議Network Protocols behind Server Push, Online Gaming, and Emails https://blog.bytebytego.com/p/network-protocols-behind-server-push ## SSE ![image](https://hackmd.io/_uploads/Hk-v1JXXJl.png) ## 位元操作 https://loesspie.com/2019/12/15/go-bitwise-operators%20/ ## websocket注意 https://github.com/jiajianrong/documents/blob/master/node/WebSocket%E9%93%BE%E6%8E%A5%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.md https://tsh.io/blog/how-to-scale-websocket/ https://www.linkedin.com/pulse/websocket-horizontal-scalability-issues-solution-ashish-wakde-jbvuf/ ## webhook ## CDN 除了靜態等會比較快 他還會中與tls 讓client不用跟server去聯繫 還有安全 能擋住ddos ## http http 1 要三次握手 而且會阻塞 所以會一次多個請求 http 2 rpc 走stream 不會阻塞 每個獨立 不會有順序等問題 而且能向客戶傳資料 http 3 使用upc (QUIC) 不用握手 是為了解決手機 5g 4g切換問題 ###### tags: `觀念重點區`