您的位置:首页 > 编程语言 > Java开发

2009-04-29技术学习:Java Socket编程

2009-04-29 17:47 501 查看
c/s模式的系统我没做过,对于Socket编程我也不懂,五一过后我就要写一个Java的Socket程序,G了一下了解个大概先。

终究还是摆脱不了千篇一律的抄啊抄,不过我也是抄!网易有一篇文章不错,因为我看的懂所以我就认为它不错!

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

java.Net包中是有关网络方面的类库,主要用到java.Net.ServerSocket(服务端使用),java.Net.Socket(客户端使用)。在Java中Socket编程很简单,它将API封装的很好,所以不用写太多的代码就可以处理客户机及服务端之间的通信了。常规来说由以下几个步骤完成:

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

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

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

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

1.一对一个的访问:

客户端:

public class Client {
Socket socket;
BufferedReader in;
PrintWriter out;
public Client() throws IOException {
try {
socket = new Socket("192.168.20.136", 10001);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader line = new BufferedReader(new InputStreamReader(System.in));

out.println(line.readLine());
line.close();
in.close();
out.close();
socket.close();
} catch (IOException e) {
}
}
}


服务端:

public class ServerOne {
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ServerOne() throws IOException{
ss = new ServerSocket(10000);
while(true){
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
String line = in.readLine();
out.println("you input is:"+line);
out.close();
in.close();
socket.close();
}
//ss.close();
}
}


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

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

PS:在这个服务端的代码中,ss.close(),根本就访问不到,不知为何还要写上,本个便注释掉了!

2.多个客户同时连接

服务端:

public class ServerTwo extends ServerSocket {
private static final int SERVER_PORT = 10000;
public ServerTwo() throws IOException {
super(SERVER_PORT);
while (true) {
Socket socket = super.accept();
new CreateServerThread(socket);
}
}
}
class CreateServerThread extends Thread {
private Socket client;
private BufferedReader in;
private PrintWriter out;
public CreateServerThread(Socket s) throws IOException {
client = s;
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
out.println("-------welcom-------");
start();
}
@Override
public void run() {
try {
String line = in.readLine();
while (!line.equals("bye")) {
String msg = createMessage(line);
out.println(msg);
line = in.readLine();
}
out.println("--------see you--------");
client.close();
} catch (IOException e) {
}
}
private String createMessage(String line) {
return " .# " + line;
}
}


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

这个程序监听10000端口,并将接入交给CreateServerThread线程运行。CreateServerThread线程接受输入,并将输入回应客户,直到客户输入"bye",线程结束。我们可以在createMessage方法中,对输入进行处理,并产生结果,然后把结果返回给客户。

3.实现信息共享:在Socket上的实时交流

服务端:

public class Server extends ServerSocket {
private static ArrayList User_List = new ArrayList();
private static ArrayList Threader = new ArrayList();
private static LinkedList Message_Array = new LinkedList();
private static int Thread_Counter = 0;
private static boolean isClear = true;
protected static final int SERVER_PORT = 10001;
protected FileOutputStream LOG_FILE = new FileOutputStream("d:/connect.log", true);
public Server() throws IOException {
super(SERVER_PORT);
new Broadcast();
//append connection log
Calendar now = Calendar.getInstance();
String str = "[" + now.getTime().toString() + "] Accepted a connection/015/012";
byte[] tmp = str.getBytes();
LOG_FILE.write(tmp);
try {
while (true) {
Socket socket = accept();
new CreateServerThread(socket);
}
} finally {
close();
}
}
//--- Broadcast
class Broadcast extends Thread {
public Broadcast() {
start();
}
@Override
public void run() {
while (true) {
if (!isClear) {
String tmp = (String) Message_Array.getFirst();
for (int i = 0; i < Threader.size(); i++) {
CreateServerThread client = (CreateServerThread) Threader.get(i);
client.sendMessage(tmp);
}
Message_Array.removeFirst();
isClear = Message_Array.size() > 0 ? false : true;
}
}
}
}
//--- CreateServerThread
class CreateServerThread extends Thread {
private Socket client;
private BufferedReader in;
private PrintWriter out;
private String Username;
public CreateServerThread(Socket s) throws IOException {
client = s;
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
out.println("--- Welcome to this chatroom ---");
out.println("Input your nickname:");
start();
}
public void sendMessage(String msg) {
out.println(msg);
}
@Override
public void run() {
try {
int flag = 0;
Thread_Counter++;
String line = in.readLine();
while (!line.equals("bye")) {
if (line.equals("l")) {
out.println(listOnlineUsers());
line = in.readLine();
continue;
}
if (flag++ == 0) {
Username = line;
User_List.add(Username);
out.println(listOnlineUsers());
Threader.add(this);
pushMessage("[< " + Username + " come on in >]");
} else {
pushMessage("<" + Username + ">" + line);
}
line = in.readLine();
}
out.println("--- See you, bye! ---");
client.close();
} catch (IOException e) {
} finally {
try {
client.close();
} catch (IOException e) {
}
Thread_Counter--;
Threader.remove(this);
User_List.remove(Username);
pushMessage("[< " + Username + " left>]");
}
}
private String listOnlineUsers() {
String s = "-+- Online list -+-/015/012";
for (int i = 0; i < User_List.size(); i++) {
s += "[" + User_List.get(i) + "]/015/012";
}
s += "-+---------------------+-";
return s;
}
private void pushMessage(String msg) {
Message_Array.addLast(msg);
isClear = false;
}
}
}


服务器端接受客户端的连接请求,同时启动一个线程处理这个连接,线程不停的读取客户端输入,然后把输入加入队列中,等候处理。在线程启动的同时将线程加入队列中,以便在需要的时候定位和取出。

客户端程序运行以后如何向服务器发送输入信息?这里我没搞定,不是程序不明白,而是在IDE运动成功后不知道如何操作。用Telnet连接就可以,我使用的是NetBeans 6.5。

今天我也是使用的网上代码,可能哪一天有人G到我的博客后也会像我一样的骂。但我以前是真的不懂Socket编程,而现在看了这篇文章之间也是真的明白了如何进行Socket编程。待模块搞定后,我再把代码奉上,实在不想做C-P的人。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: