Java 网络编程

第一步 充分理解Socket

   1.什么是socket

   所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

   Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

   重要的Socket API:

   java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK文档。

   . Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。

   . getInputStream方法获得网络连接输入,同时返回一个IutputStream对象实例,。

   . getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

   注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

   2.如何开发一个Server-Client模型的程序

   开发原理:

   服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。

   客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

第二步 多个客户同时连接

   在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序除了能处理用户的输入信息,还必须能够同时响应多个客户端的连接请求。在java中,实现以上功能特点是非常容易的。

   设计原理:

   主程序监听一端口,等待客户接入;同时构造一个线程类,准备接管会话。当一个Socket会话产生后,将这个会话交给线程处理,然后主程序继续监听。运用Thread类或Runnable接口来实现是不错的办法。

代码还不是很完善,只实现了部分功能:

1.服务器端代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
public static void main(String args[]) {
try {
ServerSocket server = new ServerSocket(4566);

try {
while (true) {
Socket socket = server.accept();
new CreateServerThread(socket);
}
} catch (IOException e) {
} finally {
server.close();
}

} catch (Exception e) {
System.out.println("Error:" + e);
}
}
}

// --- CreateServerThread
class CreateServerThread extends Thread {
private Socket client;
private BufferedReader in;
private PrintWriter out;
private BufferedReader sin;

public CreateServerThread(Socket s) throws IOException {
client = s;
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
sin = new BufferedReader(new InputStreamReader(System.in));
out.println("--- Welcome ---");
start();
}

public void run() {
try {
String line;
System.out.println("Client:" + in.readLine());
System.out.print("Server:");
line = sin.readLine();
while (!line.equals("bye")) {
out.println(line);
out.flush();
System.out.println("Client:" + in.readLine());
System.out.print("Server:");
line = sin.readLine();
}
out.println("--- See you ,bye! ---");
sin.close();
out.close();
in.close();
client.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

2.客户端代码

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientDemo {
public static void main(String args[]) {
Socket socket;
BufferedReader in;
PrintWriter out;
BufferedReader sin;
try {
socket = new Socket("127.0.0.1", 4566);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
sin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Server:" + in.readLine());
String line;
System.out.print("Client:");
line = sin.readLine();
while (!line.equals("bye")) {
out.println(line);
out.flush();
System.out.println("Server:" + in.readLine());
System.out.println("Client:");
line = sin.readLine();
}
sin.close();
out.close();
in.close();
socket.close();
} catch (Exception e) {
System.out.println("Error:" + e);
}
}
}

 第三步  图形化界面实现服务器和单客户端通信

服务器端代码:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class TestServer extends Frame implements ActionListener {
ServerSocket ss = null;
Socket s = null;
private DataInputStream is = null;
private DataOutputStream os = null;
private boolean bConnected = false;
Label ip = new Label("本机IP:");
TextField ipAddress;
Label lport = new Label("端口");
TextField tport = new TextField("8888");
Button blisten = new Button("监听");
Button close = new Button("关闭");
Panel panel = new Panel();
TextField tfTxt = new TextField();
TextArea taContent = new TextArea();
Thread tRecv = new Thread(new RecvThread());

public TestServer() {
setTitle("服务器端");
setLocation(400, 300);
setSize(500, 500);
setLayout(new BorderLayout());
panel.setLayout(new FlowLayout());
try {
ipAddress = new TextField(InetAddress.getLocalHost().toString());
} catch (HeadlessException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
panel.add(ip);
panel.add(ipAddress);
panel.add(lport);
panel.add(tport);
panel.add(blisten);
panel.add(close);
add(panel, BorderLayout.NORTH);
add(taContent, BorderLayout.CENTER);
add(tfTxt, BorderLayout.SOUTH);
blisten.addActionListener(this);
close.addActionListener(this);
tfTxt.addActionListener(this);

pack();
setVisible(true);
}

/***********************/
public void start() {
try {
int port = Integer.parseInt(tport.getText());
bConnected = true;
ss = new ServerSocket(port);
s = ss.accept();
os = new DataOutputStream(s.getOutputStream());
is = new DataInputStream(s.getInputStream());
tRecv.start();
} catch (IOException e) {
} finally {
try {
ss.close();
} catch (IOException e) {
}
}
}

/*********************************/
public void disconnect() {
try {
if (os != null)
os.close();
if (is != null)
is.close();
if (is != null)
s.close();
} catch (IOException e) {
}
}

/**********************************/

private class RecvThread implements Runnable {
public void run() {
try {
while (bConnected) {
String str = is.readUTF();
taContent.setText(taContent.getText() + "client:" + str
+ '\n');
}
} catch (EOFException e) {
taContent.setText("Client closed!");
} catch (IOException e) {
e.printStackTrace();
}

}
}

/**************************/
public void actionPerformed(ActionEvent e) {
// 如果按下的是监听按钮
if (e.getSource() == blisten) {
start();
} else if (e.getSource() == close) {
disconnect();
System.exit(0);
} else if (e.getSource() == tfTxt) {
String str = tfTxt.getText().trim();
tfTxt.setText("");
try {
os.writeUTF(str);
os.flush();
taContent.setText(taContent.getText() + "server:" + str + '\n');
} catch (IOException e1) {
}
}
}

/******************************/
public static void main(String[] args) {
new TestServer();
}

}

客户端代码:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class TestClient extends Frame implements ActionListener {
Socket s = null;
DataOutputStream os = null;
DataInputStream is = null;
private boolean bConnected = false;
Label ip = new Label("IP");
TextField ipAddress = new TextField("127.0.0.1");
Label lport = new Label("端口");
TextField tport = new TextField("8888");
Button bconnect = new Button("连接");
Button close = new Button("关闭");
Panel panel = new Panel();
TextField tfTxt = new TextField();
TextArea taContent = new TextArea();
Thread tRecv = new Thread(new RecvThread());

public void launchFrame() {
setTitle("客户端");
setLocation(400, 300);
setSize(500, 500);
setLayout(new BorderLayout());
panel.setLayout(new FlowLayout());
panel.add(ip);
panel.add(ipAddress);
panel.add(lport);
panel.add(tport);
panel.add(bconnect);
panel.add(close);
add(panel, BorderLayout.NORTH);
add(taContent, BorderLayout.CENTER);
add(tfTxt, BorderLayout.SOUTH);
bconnect.addActionListener(this);
close.addActionListener(this);
tfTxt.addActionListener(this);

pack();
setVisible(true);
}

public void connect() {
try {
String host, port;
host = ipAddress.getText();
port = tport.getText();
s = new Socket(host, Integer.parseInt(port));
os = new DataOutputStream(s.getOutputStream());
is = new DataInputStream(s.getInputStream());
bConnected = true;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/*********************************/
public void disconnect() {
try {
if (os != null)
os.close();
if (is != null)
is.close();
if (is != null)
s.close();
} catch (IOException e) {
}
}

/****************************/
private class RecvThread implements Runnable {
public void run() {
try {
while (bConnected) {
String str = is.readUTF();
taContent.setText(taContent.getText() + "server:" + str
+ '\n');
}
} catch (IOException e) {
}
}
}

/*********************************/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bconnect) {
connect();
tRecv.start();
} else if (e.getSource() == close) {
disconnect();
System.exit(0);
} else if (e.getSource() == tfTxt) {
String str = tfTxt.getText().trim();
tfTxt.setText("");
try {
os.writeUTF(str);
os.flush();
taContent.setText(taContent.getText() + "client:" + str + '\n');
} catch (IOException e1) {
}
}
}

/**********************************/
public static void main(String[] args) {
new TestClient().launchFrame();
}
/*********************************/
}
原文地址:https://www.cnblogs.com/qixin622/p/2277174.html