服务端客户端使用Go协程通信

服务端客户端使用Go协程通信

服务端

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

func main() {
	//TODO 1. 监听端口
	//TODO 2. 接收连接
	//TODO 3. 处理数据
	//TODO 4. 资源关闭 延时关闭
	listen, err := net.Listen("tcp", "127.0.0.1:8989")
	if err != nil {
		fmt.Println("监听端口失败,退出程序...,error:", err)
		return
	}
	//2. 延时关闭listen
	defer func() { _ = listen.Close() }()

	var conn net.Conn
mainOut01:
	for {
		// 阻塞
		conn, err = listen.Accept()
		// 延时关闭
		if err != nil {
			fmt.Println("获取conn失败,error: ", err)
			break mainOut01
		}
		fmt.Println(conn.RemoteAddr(), " connected the server ... ")
		//处理数据
		go ServerReceiveDataSolve(conn)
		go ServerSendData(conn)

	}
}

func ServerReceiveDataSolve(conn net.Conn) {
	// 读写一起使用的话,关闭一个,另外就不能用了
	// 延时关闭
	//defer func() { _ = conn.Close() }()
	for {
		// 1. 使用切片变量来装载字节数据
		bytes := make([]byte, 1024)
		readLen, err := conn.Read(bytes)
		if err != nil {
			fmt.Println("读取数据出现异常,error is: ", err)
			fmt.Println("客户端断开...")
			return
		}
		content := string(bytes[0:readLen])
		fmt.Printf("读到的数据内容为-:%v", content)
		if content == "quit\r\n" {
			fmt.Println("服务器端接收数据协程关闭")
			break
		}
	}
}

func ServerSendData(conn net.Conn) {
	// 延时关闭
	//defer func() { _ = conn.Close() }()
	for true {
		stdin := os.Stdin
		reader := bufio.NewReader(stdin)
		data, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("从终端获取数据失败, error is:", err)
		}
		byteSize, err := conn.Write([]byte(data))
		if err != nil {
			fmt.Println("服务端发送数据失败,error is:", err)
		}
		fmt.Println("服务端发送的内容为:", data, " 其字节大小(包含\\r\\n)为:", byteSize)
		if data == "quit\r\n" {
			fmt.Println("服务器端发送数据协程关闭")
			break
		}
	}
}

客户端

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

var (
	exetChannel = make(chan bool, 2)
)

func main() {
	// 与服务端获取连接
	conn, err := net.Dial("tcp", "127.0.0.1:8989")
	if err != nil {
		fmt.Println("获取连接失败,退出程序... error is:", err)
		return
	}
	// 延时关闭
	defer func() { _ = conn.Close() }()
	//处理数据
	go ClientSendData(conn)
	// ClientReceiveDataSolve(conn)
	go ClientReceiveDataSolve(conn)

	for {
		if len(exetChannel) == 2 {
			<-exetChannel
			<-exetChannel
			break
		}
	}
}

func ClientSendData(conn net.Conn) {
	for true {
		stdin := os.Stdin
		reader := bufio.NewReader(stdin)
		data, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("从终端获取数据失败, error is:", err)
		}
		byteSize, err := conn.Write([]byte(data))
		if err != nil {
			fmt.Println("客户端发送数据失败,error is:", err)
		}
		fmt.Println("客户端发送的内容为:", data, " 其字节大小(包含\\r\\n)为:", byteSize)
		if data == "quit\r\n" {
			fmt.Println("客户端的发送协程关闭")
			//_, _ = conn.Write([]byte("quit\r\n"))
			exetChannel <- true
			break
		}
	}
}

func ClientReceiveDataSolve(conn net.Conn) {
	for {
		bytes := make([]byte, 1024)
		nBytes, err := conn.Read(bytes)
		if err != nil {
			//if err == io.EOF {
			fmt.Println("客户端读取数据失败,error is:", err)
			break
		}
		fmt.Println("客户端读取到的内容为:", string(bytes[:nBytes]), "大小为:", nBytes)
		if string(bytes[0:nBytes]) == "quit\r\n" {
			fmt.Println("客户端的接收协程关闭")
			//_, _ = conn.Write([]byte("quit\r\n"))
			exetChannel <- true
			return
		}
	}
}

测试

服务端客户端调试过程

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java实现服务客户使用数字信封进行加密通信的代码: 服务代码: ```java import java.io.*; import java.net.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; public class Server { public static void main(String[] args) throws Exception { int port = 12345; // 生成RSA密钥对 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); // 等待客户连接 ServerSocket serverSocket = new ServerSocket(port); System.out.println("等待客户连接..."); Socket socket = serverSocket.accept(); System.out.println("客户已连接"); // 发送公钥给客户 ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(publicKey); // 接收客户发来的数字信封 ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); SealedObject sealedObject = (SealedObject)in.readObject(); // 解密数字信封 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.UNWRAP_MODE, privateKey); Key sessionKey = (Key)cipher.unwrap(sealedObject.getEncryptedKey(), "AES", Cipher.SECRET_KEY); // 使用会话密钥进行加密通信 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, sessionKey, new IvParameterSpec(new byte[16])); DataInputStream dis = new DataInputStream(socket.getInputStream()); while (true) { String message = dis.readUTF(); byte[] encryptedMessage = Base64.getDecoder().decode(message); byte[] decryptedMessage = cipher.doFinal(encryptedMessage); System.out.println("收到消息:" + new String(decryptedMessage)); } } } ``` 客户代码: ```java import java.io.*; import java.net.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; public class Client { public static void main(String[] args) throws Exception { String host = "localhost"; int port = 12345; // 连接服务 Socket socket = new Socket(host, port); System.out.println("已连接服务器"); // 接收服务公钥 ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); PublicKey publicKey = (PublicKey)in.readObject(); // 使用公钥加密会话密钥,并将数字信封发送给服务 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.WRAP_MODE, publicKey); KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(128); Key sessionKey = keyGen.generateKey(); SealedObject sealedObject = new SealedObject(sessionKey, cipher); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(sealedObject); // 使用会话密钥进行加密通信 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, sessionKey, new IvParameterSpec(new byte[16])); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { String message = br.readLine(); byte[] encryptedMessage = cipher.doFinal(message.getBytes()); String base64EncodedMessage = Base64.getEncoder().encodeToString(encryptedMessage); dos.writeUTF(base64EncodedMessage); dos.flush(); } } } ``` 注意:以上代码仅供参考,实际应用中需要进行适当的安全性改进,比如使用更长的密钥、使用更安全的加密算法等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值