Сетевое программирование
История TCP/IP 1969 году в фирме Defense Advanced Research Projects (DARPA) Larry Roberts придумал создать сеть компьютеров, связанных телефонными линиями (управление -Telnet, Network Control Protocol (NCP) ) В 1974 году Bob Kahn и Vinton Cerf, создали улучшенный протокол, названный ими Transfer Control Protocol (TCP) С 1983 протокол TCP/IP стал стандартом для сети ARPANET. В 1983 году Defense Communications Agency разделило сеть ARPANET на две части. Одну назвали Internet, а другую - Milnet.
TCP/IP протокол Модель протокола TCP/IP Application layer (слой приложения) Этот слой определяется приложением. Transport layer (транспортный уровень) Этот слой отвечает за передачу данных от одного компьютера к другому с обеспечением целостности данных. Internetwork layer (слой Интернета) На этом слое осуществляется передача данных с помощью пакетов, называемых дейтаграммами. Network Access layer (сетевой уровень) Этот слой отвечает за передачу данных через маршрутизацию компьютеров.
TCP/IP при передаче данных
java.net Socket посылает TCP сообщения ServerSocket cоздает серверы URL класс для представления адресов в виде Uniform Resource Locator URLConnection базовый класс для всех классов, реализующих связь между компьютерами.
Класс InetAddress Тим Бернерс-Ли разработал систему доменных имен. Методы для работы с IP адресами: static InetAddress getLocalHost() throws UnknownHostException static InetAddress getByName(String hostName) throws UnknownHostException static InetAddress[ ] getAllByName(String hostName) throws UnknownHostException Для удаленного узла
Класс URL (Uniform Resource Locator) URL: [protocol]://host[:port][path] import java.net.*; class classURL { public static void main(String args[j]) throws MalformedURLException { URL hp = new URL( star.com/people/naughton/"); System.out.println("Протокол: " + hp.getProtocol ()); System.out.println("Порт: " + hp.getPort()); System.out.println("Хост: " + hp.getHost()); System.out.println("Файл: " + hp.getFile()); } public class TextFromURL { int rоwData; public TextFromURL() { try { URL myURL = new URL(" URLConnection uc = myURL.openConnection(); System.out.println("Here is the HTML for this page"); InputStream is = myURL.openStream(); while((rowData = is.read()) != -1) { System.out.print((char)rowData); } is.close(); }catch (MalformedURLException mue) { System.out.println("Exception " + mue); }catch (Exception e) { System.out.println("Exception " + e); } } public static void main(String[] args) { TextFromURL tfu = new TextFromURL(); } Протокол: http Порт: -1 Хост: Файл: /people/naughton/
Программирование сокетов Классы Socket и ServerSocket Сокеты - это программный интерфейс, предназначенный для передачи данных между приложениями. Cокет – это нумерованное соединение на компьютере. Номер называется портом. Сокет определяется номером порта, IP- адресом и типом сокета. Типов сокетов два – потоковые и датаграммные. Создание сокета сервера для связи с клиентом: Socket socket = null; try { ServerSocket server = new ServerSocket(8030); socket = server.accept(); } catch (IOException e) { System.out.println("ошибка: " + e); } Сокетное соединение клиента с сервером: try { Socket socket = new Socket("localhost", 8030); } catch (IOException e) { System.out.println("ошибка: " + e); }
Класс Socket Конструкторы: Socket(String, int) - имя хоста и порт для связи. Socket(String, int, boolean) - имя хоста, порт и булевский указатель типа сокета: для потоков (true) или для датаграмм (false). Socket(InetAddress, int) – интернет-адрес и порт для связи. Socket (InetAddress, int, boolean) – интернет-адрес, порт и булевский указатель типа сокета: для потоков (true) или для датаграмм (false). close() - закрывает сокет. Для передачи данных через соединение создаем потоки ввода/вывода InputStream getInputStream() - возвращает InputStream, относящийся к данному сокету. OutputStream getOutputStream() - возвращает OutputStream, относящийся к данному сокету.
Обмен сообщением сервера с клиентом import java.io.*; import java.net.*; public class MyServerSocket{ public static void main(String[] args) throws Exception{ Socket s = null; try { //посылка строки клиенту ServerSocket server = new ServerSocket(8030); s = server.accept(); PrintStream ps = new PrintStream(s.getOutputStream()); ps.println("привет!"); ps.flush(); s.close(); // разрыв соединения } catch (IOException e) { System.out.println("ошибка: " + e); } import java.io.*; import java.net.*; public class MyClientSocket { public static void main(String[] args) { Socket socket = null; try { //получение строки клиентом socket = new Socket("имя_компьютера", 8030); BufferedReader dis = new BufferedReader( new InputStreamReader(socket.getInputStream())); String msg = dis.readLine(); System.out.println(msg); dis.close(); s.close(); } catch (IOException e) { System.out.println("ошибка: " + e); }
Двусторонняя связь public class Server { ServerSocket servSocket; Socket ClientSocket; int cTosPortNumber = 8083; String str; public Server() { try { servSocket = new ServerSocket(cTosPortNumber); ClientSocket = servSocket.accept(); ObjectOutputStream oos = new ObjectOutputStream(ClientSocket.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(ClientSocket.getInputStream()); while ((str = (String) ois.readObject()) != null) { System.out.println("The message from client is *** " + str); if (str.equals("bye")) { oos.writeObject("bye bye"); break; } else { str = "Server returns " + str; oos.writeObject(str); } oos.close(); ios.close(); ClientSocket.close(); } catch (Exception e) { System.out.println("Exception " + e); } } public static void main(String args[]) { Server lss = new Server(); } run: The message from client is *** initialize The message from client is *** Server returns initialize The message from client is *** Server returns Server returns initialize The message from client is *** Server returns Server returns Server returns initialize The message from client is *** Server returns Server returns Server returns Server returns initialize The message from client is *** bye
public class Client { Socket socket1; int portNumber = 8083; String str = ""; public Client() { try { socket1 = new Socket(InetAddress.getLocalHost(), portNumber); ObjectInputStream ois = new ObjectInputStream(socket1.getInputStream()); ObjectOutputStream oos = new ObjectOutputStream(socket1.getOutputStream()); str = "initialize"; oos.writeObject(str); int i=0; while ((str = (String) ois.readObject()) != null) { System.out.println(str); i++; if(i==5) oos.writeObject("bye"); if (str.equals("bye bye")) break; oos.writeObject(str); } ois.close(); oos.close(); socket1.close(); } catch (Exception e) { System.out.println("Exception " + e); } } public static void main(String args[]) { Client lsp = new Client(); } run: Server returns initialize Server returns Server returns initialize Server returns Server returns Server returns initialize Server returns Server returns Server returns Server returns initialize Server returns Server returns Server returns Server returns Server returns initialize bye
Многопоточность. Сервер public class NetServerThread extends Thread { Socket socket; int i; PrintStream ps; public NetServerThread(Socket s) { socket = s; try { ps = new PrintStream(s.getOutputStream()); } catch (IOException e) { System.out.println("ошибка: " + e); } } public static void main(String[] args) { Socket s = null; try { ServerSocket ser = new ServerSocket(8030); while(true){ s = ser.accept(); System.out.println("Соединение с клиентом "); NetServerThread nst = new NetServerThread(s); nst.start(); } } catch(Exception e) { System.out.println("ошибка: " + e); } } public void run() { while (true) { String msg = "сообщение: " + i++; send(msg); } public void send(String msg) { try { ps.println(msg); System.out.println(msg + " "); ps.flush(); Thread.sleep(2000); } catch (InterruptedException ex) { } }
Многопоточность. Клиент public class NetClientThread extends Thread { BufferedReader br = null; Socket s = null; public NetClientThread() { try { //соединение s = new Socket(" ", 8030); InputStreamReader isr = new InputStreamReader (s.getInputStream()); br = new BufferedReader(isr); } catch (IOException e) { System.out.println("ошибка: " + e); } } public static void main(String[] args) { NetClientThread nct = new NetClientThread(); nct.start(); } public void run() { while (true) { try { String msg = br.readLine(); if (msg == null) break; else System.out.println(msg); Thread.sleep(2000); } catch (InterruptedException ex) { } catch (IOException e) { System.out.println("ошибка: " + e); } } run: Соединение с клиентом сообщение: 0 сообщение: 1 сообщение: 2 Соединение с клиентом сообщение: 0 сообщение: 3 сообщение: 1 сообщение: 4 сообщение: 2 сообщение: 5
Датаграммы Протокол TCP/IP поддерживает доставку несвязываемых датаграмм и их возврат с помощью UDP (User Datagram Packet, "Пакет пользовательских датаграмм"). В отличие от сокетов TCP, датаграммы UDP связываются без логического соединения. Доставка датаграммы UDP не гарантирована, и даже если датаграмма доставлена, нет гарантии, что она доставлена правильно. Класс DatagramPacket: Конструкторы и методы Описание DatagramPacket(byte[], int, InetAddress, int) Создает пакет для посылки датаграммы. Содержимое массива byte посылается на порт удаленного хоста, заданный вторым целым и InetAddress. Первое целое задает число посылаемых байтов. InetAddress getAddress()Возвращает интернетовский адрес пакета. int getPort()Возвращает номер порта пакета. byte[] getData()Возвращает данные пакета. int getLength()Возвращает длину пакета.
Несвязываемые датаграммы Датаграмма – это массив байт, состоящий из заголовка, данных и окончания. Заголовок содержит адрес IP как источника данных, так и компьютера – адресата, и некоторую дополнительную информацию. Концовка обычно содержит контрольную сумму для проверки на ошибки при передаче. Класс DatagramSocket
Эхо-клиент import java.applet.*; import java.awt.*; import java.net.*; public class DatagramApplet extends Applet { private InetAddress addr; private String message; private TextArea output; public void init() { try { String me = getCodeBase().getHost(); addr = InetAddress.getByName(me); } catch (Exception e) { System.out.println(e.toString());} message = "abcde"; output = new TextArea(5,20); output.setEditable(false); add(output); show(); } public void start() { byte b[] = new byte[message.length()]; message.getBytes(0,message.length(),b,0); try { DatagramSocket ds ; ds = new DatagramSocket(7); DatagramPacket outPacket; outPacket = new DatagramPacket(b,b.length,addr,7); b = new byte[message.length()]; DatagramPacket inPacket; inPacket = new DatagramPacket(b,b.length); ds.send(outPacket); output.appendText("Sent: "+message+"\n"); ds.receive(inPacket); b = inPacket.getData(); output.appendText("Rec'd: "+new String(b)+"\n"); ds.close(); } catch (Exception e) { System.out.println(e.toString());} } public void stop() { output.setText("");} }