Java Socket编程中的线程入门

55 阅读4分钟

Java Socket编程中的线程入门

Socket编程在网络上的两台计算机之间建立了通信。套接字通信使用了两种协议。

  1. 用户数据报协议(UDP)。这是一个无连接协议。它主要用于在两个节点之间建立一个低延迟的连接。
  2. 传输控制协议(TCP)。这是一个面向连接的协议。它用于在两个节点之间建立连接。

前提条件

要跟上时代的步伐,读者需要熟悉以下内容。

  1. Java编程语言。
  2. 安装一个你选择的代码编辑器。

线程

线程允许程序通过同时做多件事情来更有效地运行。Java.lang ,负责制作和管理线程的Java.Class

为什么线程

服务器能够同时处理多个客户端也是至关重要的。具备同时管理多个消费者的能力是我们设计框架的一个要求。我们的服务器端架构需要线程,以便在每个请求到达时将其分配给一个数据输入流线程。

要创建一个新的Java线程,就必须。

  • 实现Runnable 接口。这可以通过运行java.lang.Runnable
  • 通过运行java.lang.Thread 来扩展Thread 类。

服务器端编程

下面是我们将需要的类。

服务器类

客户端的构建应从服务器的流和端口号的集合开始,然后进行以下步骤。

  • 一个while循环将建立套接字对象,接收来自服务器套接字对象的连接。
  • 我们将把请求的流纳入当前的套接字中。
  • 客户端处理程序对象是由类从流和端口号中创建的。
  • 启动程序将调用start() 方法。这个新线程对象的start() 函数必须被调用以开始运行。

ClientHandler类

线程的属性被传递给基于框架的客户处理程序类。该类的构造函数需要三个参数。Socket,DataInputStream, 和DataOutputStream 。服务器在创建Thread时得到它的端口号以及数据输入和输出流对象。

Java服务器端软件包括ServerClientHandler 类。

  1. 创建一个名为Serverclass 的新的Java类,并用下面的代码片断来更新它。
import java.io.*;
import java.text.*;
import java.util.*;
import java.net.*;
public class Serverclass
{
	public static void main(String[] args) throws IOException
	{
		ServerSocket myserverSocket = new ServerSocket(5056);
		// getting client request
		while (true)
    // running infinite loop 
		{
			Socket mynewSocket = null;
			
			try
			{
				// mynewSocket object to receive incoming client requests
				mynewSocket = myserverSocket.accept();
				
				System.out.println("A new connection identified : " + mynewSocket);
        // obtaining input and out streams
				DataInputStream ournewDataInputstream = new DataInputStream(mynewSocket.getInputStream());
				DataOutputStream ournewDataOutputstream = new DataOutputStream(mynewSocket.getOutputStream());
				
				System.out.println("Thread assigned");

				Thread myThread = new ClientHandler(mynewSocket, ournewDataInputstream, ournewDataOutputstream);
				// starting
				myThread.start();
				
			}
			catch (Exception e){
				mynewSocket.close();
				e.printStackTrace();
			}
		}
	}
}
  1. 创建一个新的Java类,命名为ClientHandler ,并用下面的代码片断进行更新。
class ClientHandler extends Thread
{
	DateFormat forourdate = new SimpleDateFormat("yyyy/MM/dd");
	DateFormat forourtime = new SimpleDateFormat("hh:mm:myserverSocket");
	final DataInputStream ournewDataInputstream;
	final DataOutputStream ournewDataOutputstream;
	final Socket mynewSocket;
	

	// Constructor
	public ClientHandler(Socket mynewSocket, DataInputStream ournewDataInputstream, DataOutputStream ournewDataOutputstream)
	{
		this.mynewSocket = mynewSocket;
		this.ournewDataInputstream = ournewDataInputstream;
		this.ournewDataOutputstream = ournewDataOutputstream;
	}

	@Override
	public void run()
	{
		String receivedString;
		String stringToReturn;
		while (true)
		{
			try {
				ournewDataOutputstream.writeUTF("Choose: [Date | Time]..\n"+
							"Or Exit");
				
				// getting answers from client
				receivedString = ournewDataInputstream.readUTF();
				
				if(receivedString.equals("Exit"))
				{
					System.out.println("Client " + this.mynewSocket + " sends exit...");
					System.out.println("Connection closing...");
					this.mynewSocket.close();
					System.out.println("Closed");
					break;
				}
				
				// creating Date object
				Date mynewDate = new Date();

				switch (receivedString) {
				
					case "Date" :
						stringToReturn = forourdate.format(mynewDate);
						ournewDataOutputstream.writeUTF(stringToReturn);
						break;
						
					case "Time" :
						stringToReturn = forourtime.format(mynewDate);
						ournewDataOutputstream.writeUTF(stringToReturn);
						break;
						
					default:
						ournewDataOutputstream.writeUTF("Invalid input");
						break;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		try
		{
			// closing resources
			this.ournewDataInputstream.close();
			this.ournewDataOutputstream.close();
			
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}
  1. 运行Serverclass 中的main 方法。

输出。

A new connection identified : Socket[addr=/127.0.0.1,port=60536,localport=5056]
Thread assigned
Client Socket[addr=/127.0.0.1,port=60536,localport=5056] sends exit...
Connection closing...
Closed

客户端编程

客户端编程和传统的套接字编程之间有许多相似之处,其中包括。

  • 建立一个套接字连接。
  • 通信。
  1. 创建一个新的Java类,命名为NewClient ,并用下面的代码片断来更新它。
import java.util.Scanner;
import java.io.*;
import java.net.*;


public class NewClient
{
    public static void main(String[] args) throws IOException
    {
        try
        {
            Scanner ourNewscanner = new Scanner(System.in);
            InetAddress inetadress = InetAddress.getByName("localhost");
            // establishing the connection 
            Socket ournewsocket = new Socket(inetadress, 3333);           
            DataInputStream ournewDataInputstream = new DataInputStream(ournewsocket.getInputStream());
            DataOutputStream ournewDataOutputstream = new DataOutputStream(ournewsocket.getOutputStream());
    // In the following loop, the client and client handle exchange data.
            while (true)
            {
                System.out.println(ournewDataInputstream.readUTF());
                String tosend = ourNewscanner.nextLine();
                ournewDataOutputstream.writeUTF(tosend);
                // Exiting from a while loo should be done when a client gives an exit message.
                if(tosend.equals("Exit"))
                {
                    System.out.println("Connection closing... : " + ournewsocket);
                    ournewsocket.close();
                    System.out.println("Closed");
                    break;
                }
                
                // printing date or time as requested by client
                String newresuiltReceivedString = ournewDataInputstream.readUTF();
                System.out.println(newresuiltReceivedString);
            }
            
            ourNewscanner.close();
            ournewDataInputstream.close();
            ournewDataOutputstream.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
  1. 运行上面NewClient 类中的main 方法。

输出。

Choose[Date | Time]..
Or Exit 
Date
2017/06/16
Choose[Date | Time]..
Or Exit 
Time
05:35:28
Choose[Date | Time]..
Or Exit 
Exit
Connection closing... : Socket[addr=localhost/127.0.0.1,port=5056,localport=60536]
Closed
  • 每次客户端请求连接到服务器时,都会创建一个新的线程。
  • 新线程一旦被分配,就会获得对所有可用流的访问。当服务器被分配时,它将接受这个请求。
  • 直到第一个请求完成后,服务器接受并处理第二个请求。

测试程序

一个接一个地运行Server.javaClient.java 。要同时执行客户端程序的众多实例,请利用类似多实例的IDE,或在不同的文件中运行客户端软件。为了得到上面显示的结果数据输入流,你将需要无数个客户端。

总结

这篇文章涵盖了套接字编程、Thread 及其使用、服务器端编程和客户端编程。

我们的实现显示了线程在Java中的重要性,在Java套接字编程中加强和理解线程。