Skip to content

Commit db78d5c

Browse files
committed
client
1 parent ccaf3cd commit db78d5c

File tree

7 files changed

+245
-0
lines changed

7 files changed

+245
-0
lines changed

client/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

client/.vscode/tasks.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"type": "cargo",
6+
"command": "run",
7+
"problemMatcher": [
8+
"$rustc"
9+
],
10+
"label": "rust: cargo run",
11+
"group": {
12+
"kind": "build",
13+
"isDefault": true
14+
}
15+
}
16+
]
17+
}

client/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "client"
3+
version = "0.1.0"
4+
authors = ["develon <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]

client/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# 3389

client/release.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc --release

client/src/main.rs

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
use std::io::{Read, Write};
2+
3+
pub static mut SERVER: Option<String> = None;
4+
pub static mut PORT: u16 = 0;
5+
pub static mut PASSWORD: Option<String> = None;
6+
pub static mut LOCAL_SERVICE: Option<String> = None;
7+
8+
fn print_help() {
9+
println!(
10+
r#"Help:
11+
{} [server:port] [bind_port] [password] [local_service:port]
12+
"#,
13+
std::env::args().nth(0).unwrap()
14+
);
15+
}
16+
17+
fn main() {
18+
let mut args = std::env::args();
19+
if args.len() < 5 {
20+
return print_help();
21+
}
22+
unsafe {
23+
SERVER = Some(args.nth(1).unwrap());
24+
PORT = match args.next().unwrap().parse() {
25+
Ok(p) => p,
26+
Err(_) => {
27+
println!(
28+
"端口号错误: {}, 请选择一个1~65535之间的端口号\n",
29+
std::env::args().nth(2).unwrap()
30+
);
31+
return print_help();
32+
}
33+
};
34+
PASSWORD = args.next().map(|s| s.to_string());
35+
LOCAL_SERVICE = args.next().map(|s| s.to_string());
36+
}
37+
loop {
38+
serv(unsafe { SERVER.as_ref().unwrap() });
39+
std::thread::sleep(std::time::Duration::from_millis(5000));
40+
}
41+
}
42+
43+
fn serv(server: &str) {
44+
println!("Connecting to {}", server);
45+
let mut conn = match std::net::TcpStream::connect(server) {
46+
Ok(conn) => conn,
47+
Err(e) => {
48+
println!("{}", e);
49+
return;
50+
}
51+
};
52+
match bind(&mut conn, unsafe { PORT }) {
53+
Ok(true) => {
54+
println!(
55+
"连接服务器成功! 服务 {} 已暴露在公网 {}{}",
56+
unsafe { LOCAL_SERVICE.as_ref().unwrap() },
57+
unsafe { SERVER.as_ref().unwrap() }.trim_end_matches(char::is_numeric),
58+
unsafe { PORT }
59+
);
60+
}
61+
Ok(false) => {
62+
println!("绑定服务器端口失败, 请检查参数!");
63+
return;
64+
}
65+
Err(e) => {
66+
println!("与服务器通信失败:{}", e);
67+
return;
68+
}
69+
}
70+
wait_conn(conn);
71+
}
72+
73+
fn bind(conn: &mut std::net::TcpStream, port: u16) -> std::io::Result<bool> {
74+
let mut buf = vec![0xba, 0xbe, ' ' as u8];
75+
let cmd = format!("{} bind {}", unsafe { PASSWORD.as_ref().unwrap() }, port);
76+
for ch in cmd.bytes() {
77+
buf.push(ch);
78+
}
79+
conn.write(&buf)?;
80+
let le = conn.read(&mut buf)?;
81+
match &buf[..le] {
82+
b"OK" => Ok(true),
83+
_ => Ok(false),
84+
}
85+
}
86+
87+
fn wait_conn(mut conn: std::net::TcpStream) {
88+
let mut buf = vec![0; 1024];
89+
loop {
90+
let le = match conn.read(&mut buf) {
91+
Ok(0) | Err(_) => {
92+
println!("连接断开!");
93+
break;
94+
}
95+
Ok(le) => le,
96+
};
97+
let msg = String::from_utf8_lossy(&buf[..le]);
98+
let cmds: Vec<&str> = msg.split(" ").collect();
99+
if let Some(cmd) = cmds.get(0) {
100+
if *cmd == "connect" {
101+
if let Some(port) = cmds.get(1) {
102+
if let Ok(port) = port.parse::<u16>() {
103+
let server = format!("{}:{}", conn.peer_addr().unwrap().ip(), port);
104+
println!("有客户端连接,中继到 {}", server);
105+
let loc = match std::net::TcpStream::connect(unsafe {
106+
LOCAL_SERVICE.as_ref().unwrap()
107+
}) {
108+
Ok(loc) => loc,
109+
Err(err) => {
110+
println!("本地服务连接失败,请检查网络,错误信息: {}", err);
111+
continue;
112+
}
113+
};
114+
let conn = match std::net::TcpStream::connect(server) {
115+
Ok(conn) => conn,
116+
Err(err) => {
117+
println!("中继端口连接失败,请检查网络,错误信息: {}", err);
118+
continue;
119+
}
120+
};
121+
relay(conn, loc);
122+
}
123+
}
124+
}
125+
}
126+
}
127+
}
128+
129+
#[inline(always)]
130+
fn a_to_b(
131+
client: &mut std::net::TcpStream,
132+
server: &mut std::net::TcpStream,
133+
buf: &mut Vec<u8>,
134+
) -> Option<bool> {
135+
match server.read(buf) {
136+
Ok(0) => {
137+
client.shutdown(std::net::Shutdown::Write).unwrap();
138+
Some(false)
139+
}
140+
Ok(le) => {
141+
client.set_nonblocking(false).unwrap();
142+
let result = match client.write(&buf[..le]) {
143+
Ok(0) => {
144+
server.shutdown(std::net::Shutdown::Read).unwrap();
145+
Some(false)
146+
}
147+
Ok(_) => Some(true),
148+
// 写入client之前设为阻塞,写入完成后设为非阻塞
149+
// Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => Some(true),
150+
Err(_e) => None,
151+
};
152+
client.set_nonblocking(true).unwrap();
153+
result
154+
}
155+
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
156+
// server would block
157+
Some(true)
158+
}
159+
Err(_e) => None,
160+
}
161+
}
162+
163+
fn relay(mut client: std::net::TcpStream, mut server: std::net::TcpStream) {
164+
std::thread::spawn(move || {
165+
let server_addr = server.peer_addr().unwrap();
166+
let client_addr = client.peer_addr().unwrap();
167+
client.set_nonblocking(true).unwrap();
168+
server.set_nonblocking(true).unwrap();
169+
let mut buf = vec![0u8; 102400];
170+
let mut sr = true;
171+
let mut cr = true;
172+
loop {
173+
if sr {
174+
match a_to_b(&mut client, &mut server, &mut buf) {
175+
Some(ok) => {
176+
if !ok {
177+
println!("服务器 {} 不向客户端 {} 发送数据", server_addr, client_addr);
178+
sr = false;
179+
}
180+
}
181+
None => break,
182+
}
183+
}
184+
185+
if cr {
186+
match a_to_b(&mut server, &mut client, &mut buf) {
187+
Some(ok) => {
188+
if !ok {
189+
println!("客户端 {} 不向服务器 {} 发送数据", client_addr, server_addr);
190+
cr = false;
191+
}
192+
}
193+
None => break,
194+
}
195+
}
196+
197+
if !sr && !cr {
198+
println!(
199+
"客户端 {} 与服务器 {} 双方都不再发送数据",
200+
client_addr, server_addr
201+
);
202+
break;
203+
}
204+
205+
std::thread::sleep(std::time::Duration::from_millis(10));
206+
}
207+
println!("结束服务 {}", client_addr);
208+
});
209+
}

0 commit comments

Comments
 (0)