本文作者:longlongago 博客地址:http://blog.youkuaiyun.com/longlongago2000
用java进行网络编程确实很方便,很容易上手。这几天用java进行socket编程,收获不少。
首先,进行服务端的编程,作为服务端,编程主要按下面几个步骤进行:
//
1. 创建socket
ServerSocket ss
=
new
ServerSocket(PortNumber);
Socket s
=
ss.accept();
//
监听器,产生阻塞,直到有连接才停止阻塞。 
//
2. 打开输入流、输出流
OutputStream os
=
s.getOutputStream();
BufferedOutputStream bos
=
new
BufferedOutputStream(os);
InputStream is
=
s.getInputStream(); 
//
3. 根据一定的协议读写数据
//
服务器 --> 客户
//
os.write("Hello,I am Server!".getBytes());
bos.write(
"
Hello,I am Server!
"
.getBytes());
bos.flush();
//
注意!! 
//
服务器 <-- 客户
byte
[] buf
=
new
byte
[
100
];
int
len
=
is.read(buf);
System.out.println(
new
String(buf,
0
, len)); 
//
4. 关系流和Socket
//
os.close();
bos.close();
is.close();
s.close();
ss.close(); 
作为客户端则分为下面几个步骤,其实和服务端差不多,只是少了用ServerSocket进行监听。
//
1. 创建socket
Socket s
=
new
Socket(InetAddress.getByName(
"
localhost
"
),
PortNumber);
//
2. 打开输入流、输出流
OutputStream os
=
s.getOutputStream();
InputStream is
=
s.getInputStream(); 
//
3. 根据一定的协议读写数据
//
服务器 --> 客户
byte
[] buf
=
new
byte
[
100
];
int
len
=
is.read(buf);
System.out.println(
new
String(buf,
0
, len));
//
服务器 <-- 客户
os.write(
"
Hello,I am Client!
"
.getBytes()); 
//
4. 关系流和Socket
os.close();
is.close();
s.close(); 
上面这些只是一个单线程的服务端->客户端的程序,只能进行一次通讯,多次通讯将被告知无法连接。
这时,我们就需要用到进程Thread进行编程,将其改造成多线程聊天程序,可以同时进行多客户端的连接与发送信息。
代码如下:
//
Server.java
import
java.awt.
*
;
import
java.net.
*
;
import
java.io.
*
; 

public
class
Server
extends
Thread
...
{
ServerSocket skt; 
Socket Client[]=new Socket[10];;
Socket Client1=null; 
int i = 0; 
TextArea in; 
int port,k=0,l=0; 
//BufferedReader theInputStream; 
PrintStream theOutputStream; 
//String readin; 
Face chat; 

public Server(int port, Face chat) ...{
try ...{
this.port = port;
skt = new ServerSocket(port);
this.chat = chat;
} catch (IOException e) ...{
chat.ta.append(e.toString());
}
} 

public void run() ...{ 
chat.ta.append("等待连线......"); 

while (true) ...{
//System.out.print(""+i+" ");
try ...{


Client[k] = skt.accept(); /**//* 接收客户连接 */
//当有客户端连接时就新建一个子线程


if (i < 2) ...{
ServerThread server[] = new ServerThread[10];
server[k]= new ServerThread(Client[k], this.chat, i);
l=server.length;
server[k].start();
chat.ta.append("客户端" + Client[k].getInetAddress() + "已连线 ");
/**//*theInputStream = new BufferedReader(new InputStreamReader(Client
.getInputStream()));*/
//for(int j=0;j<server.length;j++)
theOutputStream = new PrintStream(server[k].getClient().getOutputStream());
i = server[k].getI();
k++;
} else ...{
//theOutputStream = new PrintStream(null);
} 

} catch (SocketException e) ...{
//chat.ta.append("连线中断! "); 
//chat.clientBtn.setEnabled(true);
//chat.serverBtn.setEnabled(true);
//chat.tfaddress.setEnabled(true);
//chat.tfport.setEnabled(true);
//try { 
//skt.close();
//Client.close();
//} catch (IOException err) {
// chat.ta.append(err.toString());
//}
} catch (IOException e) ...{
chat.ta.append(e.toString());
}
} 
} 

public void dataout(String data) ...{
//for(int j=0;j<l;j++)
theOutputStream.println(data);
}
}


class
ServerThread
extends
Thread
...
{
ServerSocket skt; 
Socket client; 
TextArea in; 
int port; 
int i; 
BufferedReader theInputStream; 
PrintStream theOutputStream; 
String readin; 
Face chat; 
//服务端子线程 

public ServerThread(Socket s, Face chat, int i) ...{
this.i = ++i;
client= s;
//this.port = port;
//skt = new ServerSocket(port);
this.chat = chat; 
} 

public int getI() ...{
return this.i;
}
public Socket getClient() ...{
return this.client;
}
public void run() ...{ 
//chat.ta.append("等待连线......"); 

try ...{
//Client = skt.accept(); /* 接收客户连接 */ 
//chat.ta.append("客户端" + Client.getInetAddress() + "已连线 ");
theInputStream = new BufferedReader(new InputStreamReader(client
.getInputStream()));
theOutputStream = new PrintStream(Client.getOutputStream()); 

while (true) ...{
readin = theInputStream.readLine();
chat.ta.append(readin + " ");
} 

} catch (SocketException e) ...{
chat.ta.append("连线中断! "); 
chat.clientBtn.setEnabled(true);
chat.serverBtn.setEnabled(true);
chat.tfaddress.setEnabled(true);
chat.tfport.setEnabled(true);
try ...{
i--;
skt.close();
client.close();
} catch (IOException err) ...{
chat.ta.append(err.toString());
}
} catch (IOException e) ...{
chat.ta.append(e.toString());
}
} 

public void dataout(String data) ...{
theOutputStream.println(data);
}
}

//
Client.java
import
java.net.
*
;
import
java.io.
*
;
import
javax.swing.Timer;
class
Client
extends
Thread
...
{
Socket skt;
InetAddress host;
int port; 
BufferedReader theInputStream;
PrintStream theOutputStream;
String readin; 
Face chat; 

public Client(String ip, int p, Face chat) ...{
try ...{
host = InetAddress.getByName(ip);
port = p;
this.chat = chat;
} catch (IOException e) ...{
chat.ta.append(e.toString());
}
} 

public void run() ...{
try ...{
chat.ta.append("尝试连线......"); 
skt = new Socket(host, port);
chat.ta.append("连线成功 "); 
theInputStream = new BufferedReader(new InputStreamReader(skt
.getInputStream())); 
theOutputStream = new PrintStream(skt.getOutputStream());
//Timer myTimer = new Timer();
while (true) ...{
readin = theInputStream.readLine();
chat.ta.append(readin + " ");
}
} catch (SocketException e) ...{
chat.ta.append("连线中断! ");
chat.clientBtn.setEnabled(true);
chat.serverBtn.setEnabled(true);
chat.tfaddress.setEnabled(true);
chat.tfport.setEnabled(true);
try ...{
skt.close();
} catch (IOException err) ...{
chat.ta.append(err.toString());
}
} catch (IOException e) ...{
chat.ta.append(e.toString());
}
} 

public void dataout(String data) ...{
theOutputStream.println(data);
}
}

//
软件界面,进行按键监听调用。
//
face.java
import
java.awt.
*
;
import
java.awt.event.
*
; 

public
class
Face
extends
Frame
...
{
/** *//**
*
*/
private static final long serialVersionUID = 1L;
Button clientBtn, serverBtn;
TextArea ta;
TextField tfaddress, tfport, tftype;
int port;
Client client;
Server server;
boolean iamserver;
static Face frm; 

public Face() ...{
clientBtn = new Button("客户端");
serverBtn = new Button("服务器");
ta = new TextArea("", 10, 50, TextArea.SCROLLBARS_BOTH);
tfaddress = new TextField("192.168.1.104", 20);
tfport = new TextField("2000");
tftype = new TextField(50); 
tftype.addKeyListener(new TFListener());
ta.setEditable(false); 
setLayout(new FlowLayout());
add(tfaddress);
add(tfport);
add(clientBtn);
add(serverBtn);
add(ta);
add(tftype);
setSize(400, 300);
setTitle("我的聊天室");
this.setVisible(true); 

clientBtn.addActionListener(new ActionListener() ...{
public void actionPerformed(ActionEvent e) ...{ 
port = Integer.parseInt(tfport.getText()); 
client = new Client(tfaddress.getText(), port, frm); 
client.start(); 
tfaddress.setEnabled(false);
tfport.setEnabled(false);
serverBtn.setEnabled(false);
clientBtn.setEnabled(false);
}
}); 

serverBtn.addActionListener(new ActionListener() ...{
public void actionPerformed(ActionEvent e) ...{ 
port = Integer.parseInt(tfport.getText()); 
server = new Server(port, frm); 
server.start(); 
iamserver = true;
tfaddress.setText("成为服务器"); 
tfaddress.setEnabled(false);
tfport.setEnabled(false);
serverBtn.setEnabled(false);
clientBtn.setEnabled(false);
}
}); 

addWindowListener(new WindowAdapter() ...{
public void windowClosing(WindowEvent e) ...{
System.exit(0);
}
}); 
} 

public static void main(String args[]) ...{
frm = new Face();
} 

private class TFListener implements KeyListener ...{
public void keyPressed(KeyEvent e) ...{ 

if (e.getKeyCode() == KeyEvent.VK_ENTER) ...{ 
ta.append(">" + tftype.getText() + " "); 
if (iamserver)
server.dataout(tftype.getText());
else
client.dataout(tftype.getText()); 
tftype.setText("");
}
} 

public void keyTyped(KeyEvent e) ...{
} 

public void keyReleased(KeyEvent e) ...{
}
}
}

转载请注明:本文作者:longlongago 博客地址:http://blog.youkuaiyun.com/longlongago2000
这个程序我限制了连接数,大家可以根据自己的需要进行修改。
欢迎和我交流:email liufeituo@163.com
本文介绍了一个使用Java Socket编程实现的多线程聊天室应用,详细展示了服务端和客户端的编程流程,包括创建Socket连接、打开输入输出流、读写数据等关键步骤,并进一步介绍了如何通过多线程技术实现多客户端并发连接。
213





