Java进阶系列(包含Socket、多线程)|【大学生博客大赛】
Java进阶系列(包含Socket、多线程)
PS:本文部分转自博主自己的CSDN博客内容(链接:https://blog.csdn.net/Deardanuomi/article/details/115583822)
一:Socket网络编程
(1):Socket的步骤:
服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。
服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。
Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket
对象能够与服务器进行通信。
在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。
连接建立后,通过使用 I/O 流在进行通信,每一个socket都有一个输出流和一个输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
TCP 是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.以下是一些类提供的一套完整的有用的方法来实现 socket。
服务端代码(Server):
package Pra;
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
try
{
System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept(); //挂起,等待客户端相应
System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream()); //字节流输入,获取的的是客户端的字节流输出 ①
System.out.println(in.readUTF()); //readUTF即为获取从客户端获取的输入流 Hello from ……
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!"); //字节输出流,write给客户端 ②
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.run();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
结果:
等待远程连接,端口号为:6066…
远程主机地址:/127.0.0.1:52906
Hello from /127.0.0.1:52906
客户端代码(Cilent):
package yby;
import java.net.*;
import java.io.*;
public class GreetingClient {
public static void main(String[] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("连接到主机:" + serverName + " ,端口号:" + port); //传入的args进行打印
Socket client = new Socket(serverName, port);
System.out.println("远程主机地址是:" + client.getRemoteSocketAddress()); //获取远程主机地址
OutputStream outToServer = client.getOutputStream(); //字节流输出,反馈到服务端的字节流输入 ①
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream(); //字节输入流,获取从服务端得到的数据
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("服务器响应: " + in.readUTF()); //打印从服务端获取到的数据 谢谢连接我……
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
结果:
连接到主机:localhost ,端口号:6066
远程主机地址是:localhost/127.0.0.1:6066
服务器响应: 谢谢连接我:/127.0.0.1:6066
Goodbye!
二:I/O流区分示意图
三:多线程
(1):多线程总体思路示意图(摘自菜鸟教程)
使用以下3种方法创建多线程:
Runnable 接口
继承 Thread 类
通过 Callable 和 Future
三种代码效果:
package Lot;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//Callable 和 Future
public class Main implements Callable<Integer> {
public static void main(String[] args) {
Main ctt = new Main();
FutureTask<Integer> ft = new FutureTask<>(ctt);
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);
if (i == 1) {
new Thread(ft, "有返回值的线程").start();
}
}
try {
System.out.println("子线程的返回值:" + ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override
public Integer call() throws Exception
{
int i = 0;
for(;i<3;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
}
public class Main {
public static void main(String[] args) {
Runnable hello = new DisplayMessage("Hello");
Thread thread1 = new Thread(hello);
thread1.setDaemon(true);
System.out.println("Starting hello thread...");
thread1.start();
Runnable bye = new DisplayMessage("Goodbye");
Thread thread2 = new Thread(bye);
thread2.setPriority(Thread.MAX_PRIORITY);
System.out.println("Starting goodbye thread...");
thread2.start();
}
}
//Runnable 接口实现
class DisplayMessage implements Runnable{
private String threadname;
private Thread t;
public DisplayMessage(String name){
this.threadname=name;
System.out.println("Creating"+this.threadname+"……");
}
public void start(){
if(t==null){
t=new Thread(this,this.threadname);
t.start();
}
}
public void run(){
System.out.println("Running"+this.threadname+"……");
try{
for(int i=1;i<=3;i++){
System.out.println("Loading……第"+i+"次"+this.threadname);
Thread.sleep(100);
}
}catch(InterruptedException e){
System.out.println("Thread:"+this.threadname+"interrupted");
}
System.out.println("Thread:"+this.threadname+"exiting");
}
}
Demo thread1=new Demo("线程1");
thread1.start();
Demo thread2=new Demo("线程2");
thread2.start();
}
}
class Demo implements Runnable{
private String threadname;
private Thread rd;
public Demo(String name){
this.threadname=name;
System.out.println("建立"+this.threadname+"……");
}
public void start() { //开始进程
System.out.println("开始"+this.threadname+"……");
if(rd==null){
rd=new Thread(this,this.threadname);
rd.start();
}
}
public void run(){ //运行进程
System.out.println("运行"+this.threadname+"……");
try{
for(int i=0;i<3;i++){
System.out.println("进行"+this.threadname+"-"+i);
Thread.sleep(3000);
}
}catch(InterruptedException e){
System.out.println("进程"+this.threadname+"中断");
}
System.out.println("进程"+this.threadname+"结束");
}
}

