first commit

This commit is contained in:
free will
2021-04-30 19:00:29 +08:00
commit 89af0d2725
9 changed files with 445 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
.idea/
.git/
+101
View File
@@ -0,0 +1,101 @@
package main
// 连接子网服务器的客户端程序
import (
"TCPServerClient/utils"
"bufio"
"fmt"
"net"
"os"
"strconv"
"strings"
)
const (
DefaultServerIP = "localhost" // 服务器IP
DefaultServerPort = 50000 // 服务器端口号
DefaultRequestInfo = "Request Addr" // 请求子网IP
DefaultPassword = "12345678" // 消息加解密密码。必须是八位
)
type Client struct {
serverIP string
serverPort int
requestInfo string
password string
}
func (c *Client) start() {
// 初始化client
c.serverIP=DefaultServerIP
c.serverPort=DefaultServerPort
c.requestInfo=DefaultRequestInfo
c.password=DefaultPassword
// 连接服务器
conn, err := net.Dial("tcp", c.serverIP+":"+strconv.Itoa(c.serverPort))
if err != nil {
// 由于目标计算机积极拒绝而无法创建连接
fmt.Println("Error dialing to main server", err.Error())
return
}else{
fmt.Println("Successful conn to main server : "+conn.RemoteAddr().String())
}
// 请求子网服务器地址
subServerAddr,err:=getSubServerAddr(conn)
if err != nil {
fmt.Println("Error getSubServerAddr", err.Error())
return
}else{
fmt.Println("Successful get sub server addr: "+subServerAddr)
}
// 连接子网服务器
conn, err = net.Dial("tcp", subServerAddr)
if err != nil {
fmt.Println("Error dialing to sub server", err.Error())
return
}else{
fmt.Println("Successful conn to sub server : "+conn.RemoteAddr().String())
}
// 向子网服务器发送数据
inputReader := bufio.NewReader(os.Stdin)
fmt.Println("First, what is your name?")
clientName, _ := inputReader.ReadString('\n')
trimmedClient := strings.Trim(clientName, "\r\n") // Windows 平台下用 "\r\n"Linux平台下使用 "\n"
// 给服务器发送信息直到程序退出
for {
// 接收用户输入
fmt.Println("What to send to the server? Type Q to quit.")
input, _ := inputReader.ReadString('\n')
trimmedInput := strings.Trim(input, "\r\n")
// 判断是否要退出
if trimmedInput == "Q" {
return
}
// 发送加密数据给服务器
_, err = conn.Write([]byte(utils.EncryptMsgByDES((trimmedClient + " says: " + trimmedInput),DefaultPassword)))
}
}
func getSubServerAddr(conn net.Conn) (string,error) {
// 发送加密请求给服务器
_,err := conn.Write([]byte(utils.EncryptMsgByDES(DefaultRequestInfo,DefaultPassword)))
if err != nil {
fmt.Println("Error writing", err.Error())
return "",err
}
// 接收服务器的返回地址
buf := make([]byte, 512)
len,err := conn.Read(buf)
if err!=nil {
fmt.Println("Error reading", err.Error())
return "",err
}
return string(buf[:len]),nil
}
+7
View File
@@ -0,0 +1,7 @@
package main
func main() {
// 启动TCP客户端程序
client:=new(Client)
client.start()
}
+17
View File
@@ -0,0 +1,17 @@
package main
// 模拟子网服务器地址列表
import "net"
const (
//addr1 =
)
type AddrList struct {
addrList []net.TCPAddr
}
func (al AddrList) iniAndGetIP() (ip string,port int){
// 寻找可用子网IP,返回一个可用地址
return "localhost",50005
}
+93
View File
@@ -0,0 +1,93 @@
package main
// 分配子网边界服务器地址的服务器
import (
"fmt"
"net"
"strconv"
"TCPServerClient/utils"
)
const (
DefaultServerIP = "localhost" // 服务器IP
DefaultServerPort = 50000 // 服务器端口号
DefaultRequestInfo = "Request Addr" // 请求子网IP
DefaultPassword = "12345678" // 消息加解密密码。必须是八位
)
type Server struct {
serverIP string
serverPort int
}
// 开启server,并建立监听
func (s *Server) start() {
fmt.Println("Starting the main server ...")
// 初始化
s.serverIP=DefaultServerIP
s.serverPort=DefaultServerPort
// 创建 listener
listener, err := net.Listen("tcp", s.serverIP+":"+strconv.Itoa(s.serverPort))
if err != nil {
fmt.Println("Error listening", err.Error())
return
}
// 监听并接受来自客户端的连接,并进行处理
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting", err.Error())
return
}else{
fmt.Println("Main Server Accept conn form "+conn.RemoteAddr().String())
}
// 处理客户端请求
go doMainServerStuff(conn)
}
}
/**
处理客户端请求:只对请求子网地址的客户端连接进行响应
*/
func doMainServerStuff(conn net.Conn) {
for {
// 读取原始数据
buf := make([]byte, 512)
len, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading", err.Error())
return
}
msg:=string(buf[:len])
fmt.Println("Received raw data: %v", msg)
// 解密数据为可读格式
msg=utils.DecryptMsgByDES(msg,DefaultPassword)
fmt.Println("Received decrypt data: %v", msg)
// 判断是否是请求子网IP。是,则返回一个可用IP()
if(msg!=DefaultRequestInfo){
fmt.Println("Unable to handle request: %v", msg)
continue
}
ip,port:=searchAddr()
// 将该子网地址返回给客户端
len, err = conn.Write([]byte(ip+":"+strconv.Itoa(port)))
if err != nil {
fmt.Println("Error writing", err.Error())
}else{
fmt.Println("Send addr information to client successfully.")
}
_ = conn.Close()
return
}
}
/**
搜索子网,寻找一个可用的接入IP
*/
func searchAddr() (ip string,port int) {
addrList:=new(AddrList)
return addrList.iniAndGetIP()
}
+66
View File
@@ -0,0 +1,66 @@
package main
// 分配子网边界服务器地址的服务器
import (
"fmt"
"net"
"strconv"
"TCPServerClient/utils"
)
const (
DefaultSubServerIP = "localhost" // 服务器IP
DefaultSubServerPort = 50005 // 服务器端口号
)
type SubServer struct {
serverIP string
serverPort int
}
// 开启server,并建立监听
func (s *SubServer) start() {
fmt.Println("Starting the sub server ...")
// 初始化
s.serverIP=DefaultSubServerIP
s.serverPort=DefaultSubServerPort
// 创建 listener
listener, err := net.Listen("tcp", s.serverIP+":"+strconv.Itoa(s.serverPort))
if err != nil {
fmt.Println("Error listening", err.Error())
return
}
// 监听并接受来自客户端的连接,并进行处理
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting", err.Error())
return
}else{
fmt.Println("Sub Server Accept conn form "+conn.RemoteAddr().String())
}
// 处理客户端请求
go doSubServerStuff(conn)
}
}
/**
处理客户端请求:接收并打印客户端发来的消息
*/
func doSubServerStuff(conn net.Conn) {
for {
// 读取原始数据
buf := make([]byte, 512)
len, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading", err.Error())
return
}
msg:=string(buf[:len])
fmt.Println("Received raw data: %v", msg)
// 解密数据为可读格式
utils.DecryptMsgByDES(msg,DefaultPassword)
fmt.Println("Received decrypt data: %v", msg)
}
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"bufio"
"os"
"strings"
)
func main() {
go startSubServer()
go startMainServer()
// 等待用户输入。如果输入q,则退出程序
inputReader := bufio.NewReader(os.Stdin)
input, _ := inputReader.ReadString('\n')
trimmedInput := strings.Trim(input, "\r\n")
// 判断是否要退出
if trimmedInput == "Q" {
return
}
}
// 启动子网边界Server
func startSubServer() {
subServer:=new(SubServer)
subServer.start()
}
// 启动分配子网IP的Server处理程序
func startMainServer() {
mainServer := new(Server)
mainServer.start()
}
+104
View File
@@ -0,0 +1,104 @@
package utils
// 加密解密代码
// 参考链接:https://blog.csdn.net/sgsgy5/article/details/83584042
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
)
/**
DES加密消息
*/
func EncryptMsgByDES(msg string,password string) string {
// 加密密钥
key:=[]byte(password)
// 加密数据
result:=DesEncrypt_CBC([]byte(msg),key)
// base编码
return base64.StdEncoding.EncodeToString(result)
}
/**
DES解密消息
*/
func DecryptMsgByDES(msg string,password string) string {
// 加密密钥
key:=[]byte(password)
// base解码
baseMsg, _ :=base64.StdEncoding.DecodeString(msg)
// 解密数据
result:=DesDecrypt_CBC(baseMsg,key)
return string(result)
}
//des的cbc模式加密函数
//src :明文
//key :密钥,大小为8byte
func DesEncrypt_CBC(src ,key []byte)[]byte{ //传递两个参数,src为需要加密的明文,返回[]byte类型数据
//1:创建并返回一个DES算法的cipher.block接口
block,err:=des.NewCipher(key)
//2:判断是否创建成功
if err!=nil{
panic(err)
}
//3:对最后一个明文分组进行数据填充
src=PKCS5Padding(src,block.BlockSize())
//4:创建一个密码分组为链接模式的,底层使用DES加密的BLockMode接口
// 参数iv的长度,必须等于b的块尺寸
tmp:=[]byte("helloAAA") //初始化向量
blockmode:=cipher.NewCBCEncrypter(block,tmp)
//5:加密连续的数据块
dst:=make([]byte,len(src))
blockmode.CryptBlocks(dst,src)
//fmt.Println("加密之后的数据:",dst)
//6:将加密后的数据返回
return dst
}
//des解密函数
//src :要解密的密文
//key :密钥,和加密密钥相同,大小为8byte
func DesDecrypt_CBC(src ,key []byte)[]byte{
//1:创建并返回一个使用DES算法的cipher.block接口
block,err:=des.NewCipher(key)
//2:判断是否创建成功
if err!=nil{
panic(err)
}
//创建一个密码分组为链接模式的,底层使用DES解密的BlockMode接口
tmp:=[]byte("helloAAA")
blockMode:=cipher.NewCBCDecrypter(block,tmp)
//解密数据
dst:=make([]byte,len(src))
blockMode.CryptBlocks(dst,src)
//5:去掉最后一组填充数据
dst=PKCS5UnPadding(dst)
//返回结果
return dst
}
//使用pkcs5的方式填充
func PKCS5Padding(ciphertext []byte,blockSize int)[]byte{
//1:计算最后一个分组缺多少字节
padding:=blockSize-(len(ciphertext)%blockSize)
//2:创建一个大小为padding的切片,每个字节的值为padding
padText:=bytes.Repeat([]byte{byte(padding)},padding)
//3:将padText添加到原始数据的后边,将最后一个分组缺少的字节数补齐
newText:=append(ciphertext,padText...)
return newText
}
//删除pkcs5填充的尾部数据
func PKCS5UnPadding(origData []byte)[]byte{
//1:计算数据的总长度
length:=len(origData)
//2:根据填充的字节值得到填充的次数
number:=int(origData[length-1])
//3:将尾部填充的number个字节去掉
return origData[:(length-number)]
}
+20
View File
@@ -0,0 +1,20 @@
package utils
import (
"fmt"
"testing"
)
// 测试加密解密
func TestEncryptAndDecrypt(t *testing.T) {
password:="1234567890"
enMsg:=encryptMsg("这是一个测试字符串",password)
fmt.Println("加密后字符串:"+enMsg)
deMsg:=decryptMsg(enMsg,password)
fmt.Println("解密后字符串:"+deMsg)
}
//// 测试解密
//func TestDecrypt(t *testing.T) {
//
//}