先上代码,这个是部署在公网服务器的代码,必须要有固定IP地址。各个客户端必须能用服务器IP连接。下面的代码只能接受显示来自客户端的信息,还不能转发
创新互联建站坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、做网站、成都外贸网站建设公司、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的九江网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!其实原理很简单:各个客户端通过Socket 与服务器连接上,服务器监听与客户端连接的端口,通过软件操作,把收到的各个端口信息分别发给对应的端口。这个场景就像QQ ,微信 ,vpn ,代理,隧道,文件共享等等,你只要为一个客户端写某种请求功能后,其他的客户端就可以通过端口享受这种功能
1.利用线程在一个程序中监控两个端口(服务器代码)
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(3000); //理论上可以开无数多个端口
ServerSocket ss1=new ServerSocket(3001);
Thread t1 = new T1(ss); //经验证,while内 不能有Thread循环,会报错
Thread t2 = new T2(ss1);
t1.start();
t2.start();
}
static class T1 extends Thread{
ServerSocket ssi;
T1(ServerSocket ssi) { //T1构造函数,为T1赋初值
this.ssi = ssi;
}
public void run() {
try {
while(true) {
Socket sc = ssi.accept(); //经验证,ServerSocket 不能用在线程中,否则回报端口占用的错误
InputStream is = sc.getInputStream();
byte[] b = is.readAllBytes();
System.out.println(new String(b));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
static class T2 extends Thread{
ServerSocket ssi1;
T2(ServerSocket ssi1) {
this.ssi1 = ssi1;
}
public void run() {
try {
while(true) {
Socket sc1 = ssi1.accept();
InputStream is1 = sc1.getInputStream();
byte[] b1 = is1.readAllBytes();
System.out.println(new String(b1));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
客户端可以没有外网固定IP,如在192.168号段内,只要能连接上服务器就可以了。通过服务器的软件操作,在各个端口间调用信息,客户端之间就可以通信了,就如QQ一样,T1,T2之间可以互发信息。
客户端代码:下面的客户端代码为socket短连接,现只能发送信息,如要收到服务器的信息,必须和服务器长连接,就像QQ一直在线一样。所以要去掉os.close(),再加一个循环等待。一直监控服务器方的数据输入。为客户端分配端口号,就相当于QQ注册。QQ掉线,就相当于socket关闭。客户端之间断开。
import java.net.Socket;
import java.io.*;
public class Con1{
public static void main(String[] args) throws IOException{
Socket sc=new Socket("127.0.0.1",3001);
OutputStream os=sc.getOutputStream();
os.write("hello1".getBytes());
System.out.println("ok");
os.close();
}
}
上图为服务器部署在本机,客户端访问127.0.0.1 的显示结果
服务器内端口信息转发的思路:为每一个端口配一个接收标志位,输出标志位,接收存储区,输出存储区。如果是多端口,再配一个目标端口位。服务器根据标志位的状态,和目标端口号,把相应端口号的信息互换,完成端口转发。
2.socket长连接:客户端与服务器之间双向传输数据代码
客户端代码:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Con {
public static void main(String[] args) throws IOException {
String data;
while(true) {
Scanner scan = new Scanner(System.in);
String sin = scan.nextLine();
data =sin;
Socket sc = new Socket("114.132.48.228", 3000);
OutputStream os = sc.getOutputStream();
os.write((data+'\n').getBytes(StandardCharsets.UTF_8)); //数据结尾一定要加\n,经验证
System.out.println("send over");
InputStream is=sc.getInputStream();
String s="";
int t=is.read();
while((char)t!='\n'){ //通过\n来判断输入完成
s=s+(char)t;
t=is.read();
}
System.out.println(s);
}
}
}
服务器端代码:
import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.io.*;
public class Server1 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(3000);
while(true) {
Socket sc=ss.accept();
InputStream is=sc.getInputStream();
String s="";
int t=is.read();
while((char)t!='\n'){
s=s+(char)t;
t=is.read();
}
System.out.println(s);
OutputStream os=sc.getOutputStream();
os.write("server send:hello\n".getBytes());
System.out.println("server:send over");
// sc.close();
}
}
}
经验证,这里不能用InputStream is=sc.getInputStream();
byte[] b=is.readAllBytes();
只能用原始的int t=is.read();
特别注意:客户端和服务器端传输数据末尾必须加'\n',作为判断符号,当然,也可以换成其他符号如:^ ,~ 等非常用符号,甚至^~两个符号连用,但要改变while判断语句。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧