随手敲代码回顾下socket,先直接上代码了
public class TestThread {
private static int[] port = {8090,8091,8092,8093,8094};
public class SendThread implements Runnable{
private int port;
private String ip;
public SendThread(int port,String ip){
this.port = port;
this.ip = ip;
}
@Override
public void run() {
Socket socket = new Socket();
PrintWriter socketOut = null;
SocketAddress remoteAddr = new InetSocketAddress(ip, port);
try {
socket.connect(remoteAddr,120000);
Writer writer = new OutputStreamWriter(socket.getOutputStream(),"utf-8");
socketOut = new PrintWriter(socket.getOutputStream());
socketOut.write("*");
socketOut.flush();
socket.shutdownOutput();
System.out.println("往"+ip+":"+port+"发送*");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiveThread implements Runnable{
private int port;
public ReceiveThread(int port){
this.port = port;
}
@Override
public void run() {
Socket socket = new Socket();
ServerSocket server = null;
try {
server = new ServerSocket(port);
server.setSoTimeout(600000);
socket = server.accept();
//获得ip地址
String ip = socket.getInetAddress().getHostAddress();
//跟客户端建立好连接之后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了。
Reader reader = new InputStreamReader(socket.getInputStream(),"UTF-8");
BufferedReader bufferedReader = new BufferedReader(reader);
String result = bufferedReader.readLine();
char[] chars = result.toCharArray();
System.out.println("从"+ip+":"+port+"获取到"+chars[0]);
reader.close();
socket.close();
server.close();;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testSend(){
for (int i = 0; i < 5; i++) {
new Thread(new SendThread(port[i],"192.168.1.191")).run();
}
}
@Test
public void testReceive(){
for (int i = 0; i < 5; i++) {
new Thread(new ReceiveThread(port[i])).run();
}
}
}
简单的一个本机的自发自接,先启动接受方,再启动发送方,运行结果:
光从结果来说,乍一看没什么问题,但细心的同学可能会发现问题所在,且是一个很大的问题。这里我就不卖关子了,我就稍微在代码里面做下输出提示,在红色标注的地方插入
System.out.println("端口号:"+port+"开始接受");
结果再运行一下,先运行接收方,你会发现控制台只打印出了一句话,再运行发送方,就把内容都打印出来了
结果不是很令人满意,等于说按照了for循环执行的顺序来运行得出结果,那我开启多线程岂不是没有意义?
为什么会出现控制台只打印出一个结果?
我们都知道接受的时候会在accept的地方阻塞住,直到接受到消息才继续往下执行,换句话说控制台出现一个结果,恰恰表明了程序执行到第一个循环开启第一个线程执行accept的地方就卡主了。通过打断点你也可以发现,for循环执行到第一个线程开启的地方再往下就执行不下去了。原因就在于,开启线程使用的是run方法,而run方法并不是真正意义上的开启线程,只不过是把Runnable中的run方法执行了一遍而已,所以看似循环开启多个线程,实际上就只是按顺序把run方法挨个执行一遍而已。所以要开启多线程来接发,还是得调用start方法。