сряда, 14 януари 2009 г.

Java sockets

Обикновено един сървър работи на дадена машина, слуша на определен порт и чака клиент, който да направи заявка за свързване с този сървър. Клиентът пък, като знае адреса на машината, на която работи сървърът, и номера на порта, на който сървърът слуша, се опитва да се свърже с него на този адрес и порт, като също се идентифицира пред него. Ако всичко мине нормално, сървърът приема свързването и получава нов сокет, който е свързан със същия локален порт, а на другия му край са адресът и портът на клиента. Създава се нов сокет, чрез който сървърът да обслужи свързания клиент, а на стария продължава да слуша за опити за свързване. При клиента, ако се установи връзка, се създава сокет, който клиентът да използва за комуникация със сървъра.

В пакета java.net има клас Socket, който представя едната страна на двупосочна връзка. Има и клас ServerSocket, който представя сокет, който сървърите могат да използват за слушане и приемане на връзки с клиенти.
Класът java.net.Socket има следните конструктори, в зависимост от това дали за сървъра, с който искаме да се свържем, се задава IP адрес или име на хост; както и в зависимост от това дали се задават локален адрес и номер на порт или се използват тези по подразбиране:
Socket();
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, InetAddress localAddr, int localPort);
Socket(String host, int port);
Socket(String host, int port, InetAddress localAddr, int localPort);
Ако host е null, то се взима loopback адреса (т.е. за host се подава стойността, получена при извикване на InetAddress.getByName(null)).

Класът java.net.InetAddress представя IP адрес + евентуално име на хост. Има следните методи:
public boolean isReachable(int timeout) throws IOException;
public String getHostName();
public byte[] getAddress(); // в network byte order
public String getHostAddress();
public static InetAddress getByAddress(String host, byte[] addr);
public static InetAddress getByName(String host);
public static InetAddress getByAddress(byte[] addr);
public static InetAddress getLocalHost();
public static InetAddress[] getAllByName(String host);

Методи на класа java.net.Socket:
void bind(SocketAddress bindpoint);
boolean isBound();
void connect(SocketAddress endpoint);
void connect(SocketAddress endpoint, int timeout);
boolean isConnected();
InetAddress getInetAddress();
int getPort();
InetAddress getLocalAddress();
int getLocalPort();
InputStream getInputStream();
OutputStream getOutputStream();
void shutdownInput();
void shutdownOutput();
boolean isInputShutdown();
boolean isOutputShutdown();
void close();
boolean isClosed();

Конструктори на класа java.net.ServerSocket:
ServerSocket();
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr);
Празният конструктор създава несвързан сървърски сокет. Вторият конструктор създава сървърски сокет, който е свързан към зададения порт (ако е посочено 0, то се използва кой да е свободен порт). С третия конструктор може да се зададе максимална дължина на опашката от чакащи клиенти (при втория конструктор, като не е зададена максимална дължина на опашката, стойността по премълчаване е 50). В четвъртия случай параметърът bindAddr указва локалния IP адрес, към който да се свърже сокетът, при наличие на повече от един такива адреси.

Методи на класа java.net.ServerSocket:
void bind(SocketAddress endpoint);
void bind(SocketAddress endpoint, int backlog);
boolean isBound();
Socket accept();
InetAddress getInetAddress();
int getLocalPort();
void close();
boolean isClosed();
Чрез метода accept сървърът започва да слуша за опити за осъществяване на връзка с него и приема връзка, ако се появи искане за такава. Методът заключва, докато не се установи връзка. Създава се нов обект Socket.

Прост клиент/сървър на Java



import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;

import java.net.ServerSocket;
import java.net.Socket;


public class EchoServer {
public static void main(String[] args) {

// Declare a server socket and a client socket for the server
ServerSocket echoServer = null;
Socket echoClient = null;

// Declare an input and an output stream
DataInputStream is;
PrintStream os;

String line;

// Try to open a server socket on port 9999
try {
echoServer = new ServerSocket(9999);
} catch (IOException e) {
System.out.println(e);
}

try {
// Create a client socket object from the ServerSocket
echoClient = echoServer.accept();

// Open input and output streams
is = new DataInputStream(echoClient.getInputStream());
os = new PrintStream(echoClient.getOutputStream());

// As long as we receive data, echo that data back to the client
while (true) {
line = is.readLine();
os.println(line);
}
} catch (IOException e) {
System.out.println(e);
}
}
}
import java.io.*;
import java.net.*;

public class EchoClient {
public static void main(String[] args) throws IOException {

// Declare a client socket
Socket echoClient = null;

// Declare an input and an output stream
PrintWriter out = null;
BufferedReader in = null;

String host = "localhost";

try {
// Try to connect to the specified host (localhost) at port 9999
echoClient = new Socket(host, 9999);

// Open input and output streams
out = new PrintWriter(echoClient.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoClient.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + host);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " +
"the connection to: " + host);
System.exit(1);
}

// Declare and initialize a reader from standard input
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String userInput;

// As long as data is written to standard input, send that data
// to the server and then print on standard output what is
// received from the server
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}

out.close();
in.close();
stdIn.close();
echoClient.close();
}
}

Няма коментари:

Публикуване на коментар