SimpleNet is a simplistic, client-server framework written in Java. One or more Client
objects can connect to a Server
and send data back-and-forth via TCP. Most methods that read data from the network are non-blocking and are invoked asynchronously when the requested data arrives. Not having to block a thread and wait for data is what makes SimpleNet scalable for different types of applications such as chat servers, multiplayer game servers, and so much more!
Maven:
<dependency>
<groupId>com.github.jhg023</groupId>
<artifactId>SimpleNet</artifactId>
<version>1.6.6</version>
</dependency>
Gradle:
implementation 'com.github.jhg023:SimpleNet:1.6.6'
module-info.java
:module my.project {
requires com.github.simplenet;
}
n
, and specify what should be done with those n
bytes, as if the Client
or Server
has already received them.// Request a single byte and print it out when it arrives.
client.readByte(System.out::println);
// Continuously request a single byte and print it out when it arrives.
//
// After the callback completes, another byte will be requested automatically,
// and the same callback will be invoked. This continues until the connection is closed.
client.readByteAlways(System.out::println);
Client
to a Server
(and vice versa) via the Packet
class.// Create a packet that contains two bytes (with the value 42) and send it to a client.
Packet.builder().putByte(42).putByte(42).queueAndFlush(client);
// Create two packets with the specified data and queue them (but don't flush) to a client.
Packet.builder().putInt(123456).queue(client);
Packet.builder().putString("Hello World!").queue(client);
// Flush the queued packets to the client (these packets will be transformed into a single,
// big packet to improve throughput.
//
// This method only needs to be called when using Packet#queue and not Packet#queueAndFlush.
client.flush();
// Instantiate a new client.
var client = new Client();
// Register a connection listener.
client.onConnect(() -> {
System.out.println(client + " has connected to the server!");
// Builds a packet and sends it to the server immediately.
Packet.builder().putByte(1).putInt(42).queueAndFlush(client);
});
// Register a pre-disconnection listener.
client.preDisconnect(() -> System.out.println(client + " is about to disconnect from the server!"));
// Register a post-disconnection listener.
client.postDisconnect(() -> System.out.println(client + " successfully disconnected from the server!"));
// Attempt to connect to a server AFTER registering listeners.
client.connect("localhost", 43594);
// Instantiate a new server.
var server = new Server();
// Register one connection listener.
server.onConnect(client -> {
System.out.println(client + " has connected!");
/*
* When one byte arrives from the client, switch on it.
* If the byte equals 1, then request an int and print it
* when it arrives.
*
* Because `readByteAlways` is used, this will loop when
* the callback completes, but does not hang the executing thread.
*/
client.readByteAlways(opcode -> {
switch (opcode) {
case 1:
client.readInt(System.out::println);
}
});
// Register a pre-disconnection listener.
client.preDisconnect(() -> System.out.println(client + " is about to disconnect!"));
// Register a post-disconnection listener.
client.postDisconnect(() -> System.out.println(client + " has successfully disconnected!"));
});
// Bind the server to an address and port AFTER registering listeners.
server.bind("localhost", 43594);
To emphasize how easy it is to use SimpleNet, I have written an implementation of a scalable chat server below. Note how only two classes are required, ChatServer
and ChatClient
. Ideally, a chat server should use a GUI and not the console, as this leads to message cut-off in the window, but this is only to serve as a proof-of-concept.
The full ChatServer
implementation is as follows:
public class ChatServer {
public static void main(String[] args) {
// Initialize a new server.
var server = new Server();
// Create a map that will keep track of nicknames on our chat server.
var nicknameMap = new ConcurrentHashMap<Client, String>();
// This callback is invoked when a client connects to this server.
server.onConnect(client -> {
// When a client disconnects, remove them from the nickname map.
client.postDisconnect(() -> nicknameMap.remove(client));
// Repeatedly read a single byte.
client.readByteAlways(opcode -> {
switch (opcode) {
case 1: // Change nickname
client.readString(nickname -> nicknameMap.put(client, nickname));
break;
case 2: // Send message to connected clients.
client.readString(message -> {
message = nicknameMap.get(client) + ": " + message;
server.queueAndFlushToAllExcept(Packet.builder().putString(message), client);
});
break;
}
});
});
// Bind the server to our local network AFTER registering listeners.
server.bind("localhost", 43594);
}
}
The full ChatClient
implementation is as follows:
public class ChatClient {
public static void main(String[] args) {
// Initialize a new client.
var client = new Client();
// This callback is invoked when this client connects to a server.
client.onConnect(() -> {
var scanner = new Scanner(System.in);
// If messages arrive from other clients, print them to the console.
client.readStringAlways(System.out::println);
System.out.print("Enter your nickname: ");
Packet.builder().putByte(1).putString(scanner.nextLine()).queueAndFlush(client);
// Infinite loop to accept user-input for the chat server.
while (true) {
System.out.print("> ");
// Read the client's message from the console.
var message = scanner.nextLine();
// If this client types "/leave", close their connection to the server.
if ("/leave".equals(message)) {
client.close();
break;
}
// Otherwise, send a packet to the server containing the client's message.
Packet.builder().putByte(2).putString(message).queueAndFlush(client);
}
});
// Attempt to connect to a server AFTER registering listeners.
client.connect("localhost", 43594);
}
}
onConnect
callback?
onConnect
callback is performed asynchronously.Client
be used with some unrelated server and vice-versa?
Client
and Server
have an overloaded constructor that accepts a buffer size in bytes. You can simply specify a size larger than 8192 (the default size).# coding: utf-8 #深度学习入门基于python的理论与实现 4章gradient_simplenet.py 完全解析 import sys, os sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定 import numpy as np from common.functions import softmax, cross_entropy
本文从最基础的梯度下降原理出发,使用numpy库搭建一个简单的神经网络。 主要函数: softmax:对于分类问题,使用恒等函数作为显然并不合适,因此设计softmax函数,其基本原理就是将用二进制矩阵表示的输出经过softmax将其最大预测概率输出,比如某一类别真实值为[0,0,1],经过softmax函数后输出为[0.1,0.2,0.7],那么就可认为最大的概率0.7为“1",其余各位为0,从
DL之simpleNet:利用自定义的simpleNet(设好权重)对新样本进行预测、评估、输出梯度值 导读 理解神经网络内部的数学机制 目录 输出结果 核心代码 输出结果 输出权重参数: [[-0.94465146 -1.22617291 0.89064915] [-0.36625531 1.57482914 0.82170746]] 输出预测: [-0.896420
背景 在FATE1.10,原生的homo nn的场景只能支持torch Sequential来的模型,也就是这样的 model = t.nn.Sequential( t.nn.Linear(784, 32), t.nn.ReLU(), t.nn.Linear(32, 10), t.nn.Softmax(dim=1) ) 不支持用Class定义的,但是sequent
#以一个简单的神经网络为例,来实现求损失函数关于权重参数的梯度 #刚开始看 记录一下笔记 import sys, os sys.path.append(os.pardir) import numpy as np from common.functions import softmax, cross_entropy_error # softmax 交叉熵函数 from common.gradie