Section 15 network and threads

Port

A port represents a logical connection to a particular piece of software. A number representing an application.

TCP port from 0 to 1023 are reserved for well known services.


Client:

Read data from a Socket:

Socket socket = new Socket("127.0.0.1", 5000);
// Chain socket connection stream to a high-level character stream
InputStreamReader stream = new InputStreamReader(socket.getInputStream());
BufferedReader reader = new BufferedReader(stream);
// BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = reader.readLine();
reader.close();


Write data to a Socket:

Socket socket = new Socket("127.0.0.1", 5000);
// Chain socket connection stream. Character to bytes. PrintWriter is the standard choice for writing one String at a time.
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println("Hello");
writer.pirnt("No new line");
writer.close();


 

Server:

ServerSocket serverSocket = new ServerSocket(5000);
// This socket is on a different port so server can continue listen on 5000.
Socket socket = serverSocket.accept();

Thread: 

A thread is a separate thread of execution. A separate call stack.

A runnable is the job for a thread. The runnable interface only has one method run(), which is put at the bottom of the call stack first to run.

A thread state: 

runnable: ready to run, wait for JVM scheduler to select.

running:

blocking:

dead:

To make a thread in 3 ways:

public class Threadtest {
	// Inner Class Runnable 成员内部类
	class MyRunnable implements Runnable {
		@Override
		public void run() {
			System.out.println("In my runnable");
		}
	}
	
	public static void main(String[] args) {
		// Override run() in Thread
		Thread t1 = new Thread() {
			@Override
			public void run() {
				System.out.println("In a thread!");
			}
		};
		t1.start();
		
		// Inner class runnable. Calling inner class constructor.
		Threadtest tt = new Threadtest();
		Runnable myRunnable = tt.new MyRunnable(); // Threadtest.MyRunnable myRunnable = tt.new MyRunnable();
		Thread t2 = new Thread(myRunnable);
		t2.start();
		
		// Use Runnable
		Thread t3 = new Thread(new YourRunnable());
		t3.start();
		
		System.out.println("In main");
	}
}

class YourRunnable implements Runnable {
	@Override
	public void run() {
		System.out.println("In a your runnable");
	}
}
Runnable is an interface, but it can be a reference type.


Thread scheduling is not guaranteed to work in any particular way. You shouldn't rely on it.

After sleep(), the thread becomes runnable. Not immediately running.


synchronized block is atomic.

You can't have two threads entering any of a object's synchronized methods at the same time. Among all synchronized methods, only one synchronized method can be executed at any time. Synchronized methods use its object's lock. Synchronized methods might work on the same instance variables so only one synchronized method is invoking at a time. 


Lost Update problem:

int i = balance;
balance = i + 1;
Thread can switch between two statements.

A simple ChatRoom with GUI code:

Client Code:

public class Client {
	private JTextArea incoming;
	private JTextField outgoing;
	private BufferedReader reader;
	private PrintWriter writer;
	private Socket socket;

	public Client() {
		JFrame frame = new JFrame("A Simple Chat Client");
		JPanel mainPanel = new JPanel();
		
		incoming = new JTextArea(15, 50);
		incoming.setLineWrap(true);
		incoming.setWrapStyleWord(true);
		incoming.setEditable(false);
		
		JScrollPane qScroller = new JScrollPane(incoming);
		qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		
		outgoing = new JTextField(20);
		
		JButton sendButton = new JButton("Send");
		sendButton.addActionListener(new SendButtonListener());
		
		mainPanel.add(qScroller);
		mainPanel.add(outgoing);
		mainPanel.add(sendButton);
		
		setUpNetworking();

		Thread readerThread = new Thread(new IncomingReader());
		readerThread.start();

		frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(600, 500);
		frame.setVisible(true);
	}

	private void setUpNetworking() {
		try {
			socket = new Socket("127.0.0.1", 5000);
			reader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			writer = new PrintWriter(socket.getOutputStream());
			System.out.println("Networking established!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class SendButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			String message = outgoing.getText();
			if(message == null || message.length() == 0) {
				return;
			}
			writer.println(message);
			if(writer.checkError()) {
				incoming.append("Server is down! Please close and restart client.");
				return;
			} // writer does not throw exception. when server is down, it cannot detect.
			outgoing.setText("");
			outgoing.requestFocus();
		}
	}

	class IncomingReader implements Runnable {
		@Override
		public void run() {
			String message = null;
			try {
				while ((message = reader.readLine()) != null) {
					incoming.append(message + "\n");
				}
			} catch (IOException e) {
				return;
			}
		}
	}
	
	public static void main(String[] args) {
		Client client = new Client();
	}
}

Server Code:
public class Server {
	ServerSocket server;
	ArrayList<PrintWriter> clientWriters;

	public Server() {
		try {
			server = new ServerSocket(5000);
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		clientWriters = new ArrayList<PrintWriter>();
	}

	public void run() {
		while (true) {
			Socket socket;
			try {
				socket = server.accept();
				PrintWriter writer = new PrintWriter(socket.getOutputStream());
				clientWriters.add(writer);
				Thread serverThread = new Thread(new ClientHandler(socket));
				serverThread.start();
				System.out.println("Got a connection");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	class ClientHandler implements Runnable {
		BufferedReader reader;
		private ClientHandler(Socket socket) {
			try {
				reader = new BufferedReader(new InputStreamReader(
						socket.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			String message = null;
			try {
				while ((message = reader.readLine()) != null) {
					sendOutMessage(message);
					System.out.println("Got message: " + message);
				}
			} catch (IOException e) {
				return;
			}
		}

		private void sendOutMessage(String message) {
			Iterator<PrintWriter> it = clientWriters.iterator();
			while (it.hasNext()) {
				PrintWriter writer = (PrintWriter) it.next();
				writer.println(message); //writer does not throw exception.
				//writer.flush();
				if(writer.checkError()) {
					System.out.println("Client is down!");
					it.remove();
				}
			}
		}
	}

	public static void main(String[] args) {
		Server server = new Server();
		server.run();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值