JavaSocket网络编程
Java Socket网络编程
计算机网络中,客户机与服务器之间进行通信时,客户机必须知道服务器的IP地址和端口号。IP地址是标识Internet网络中的某台计算机,而端口号则标识着在服务器上运行的某个程序(进程),如果在服务器上运行的程序,没有端口号,则客户端的程序就不能找到它,也不能和它进行通信。一定要清楚,别和电脑上的物理端口号搞混了。 端口号是一个逻辑的地址,用于标识计算机中运行着的应用程序。它可以是0~65535之间的一个数,0~1023为系统保留使用,例如http的是80端口等,这些是系统已经分配给默认服务使用的。 当两个应用程序需要通过网络通信时,就可以使用IP地址和端口号进行通过,IP地址和端口号组合在一起就是一个Socket(网络套接字)。套接字分为服务端的和客户端的两种
一、客户端套接字
客户端的套接字用于与服务器端的套接字进行连接。其使用方法如下:
socket=new Socket("127.0.0.1",2018);
其中127.0.0.1标识服务器端的IP地址,2018标识服务器端应用程序的端口号。在建立套接字的过程中,可能会发生IOException异常,要注意进行处理。
二、服务器端套接字
客户端与服务器端通信时,服务器端负责提供服务,客户端通过Socket向服务器端请求服务。因此,在服务器端也必须有相应的套接字与客户端进行连接。使用如下:
try { serverSocket=new ServerSocket(2018);
socket=serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
ServerSocket的构造方法中,只有一个参数,即Port号,需要注意的是,服务器端的Port号必须与客户端的相同。
当调用ServerSocket的accept()方法时,会返回一个客户端套接字对象,即Socket对象。该对象在客户端与服务端连接的过程中,将驻留在服务器的内存中,我们通过它就可以与客户端进行数据的传输。
三、客户端与服务端通信的简单实现
客户端与服务端通信时,首先服务端要在相应的端口进行监听,等待客户端的连接请求。然后在客户端请求时,接受客户端的请求,然后进行通信。首先是服务端。代码如下:
package socket.demo2;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServerFrame extends JFrame{
//接收客户端发送的消息
private JTextArea allMessage=new JTextArea(8,20);
// 输入发送给客户端的消息
private JTextField sendMessage=new JTextField(20);
//消息发送按钮
private JButton sendBtn=new JButton("发送");
private JButton startServer=new JButton("开始服务器");
private ServerSocket serverSocket=null;//服务器端Socket
private BufferedReader in=null;//用于接收客户端发送的数据
private BufferedWriter out=null;//用于发送数据给客户端
private Socket socket=null;//客户端连接对象
private int port;
public void setPort(int port){
this.port=port;
}
public MyServerFrame(){
init();
}
private void init(){
setTitle("服务端");
setLayout(new BorderLayout());
//开始服务器按钮单击事件
startServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
serverSocket=new ServerSocket(port);
socket=serverSocket.accept();
new receiverMsgThread().start();//启动线程接收客户端数据
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//发送按钮单击事件
sendBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write(sendMessage.getText());
out.newLine();
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//将组件添加到窗体中
JPanel panel=new JPanel();
panel.add(startServer);
panel.add(sendMessage);
panel.add(sendBtn);
add(allMessage,BorderLayout.CENTER);
add(panel,BorderLayout.SOUTH);
//配置窗体
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
//接收信息线程
class receiverMsgThread extends Thread{
public void run(){
try {
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str=null;
while (true){
str=in.readLine()+"\n";
allMessage.append("客户端说:"+str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerFrame myServerFrame=new MyServerFrame();
myServerFrame.setPort(12345);
}
}
客户端代码如下:
package socket.demo2;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
public class MyClientFrame extends JFrame{
//接收客户端发送的消息
private JTextArea allMessage=new JTextArea(8,20);
// 输入发送给客户端的消息
private JTextField sendMessage=new JTextField(20);
//消息发送按钮
private JButton sendBtn=new JButton("发送");
private JButton connServer=new JButton("连接服务器");
private Socket socket=null;
private BufferedReader in=null;
private BufferedWriter out=null;
public MyClientFrame(){
init();
}
private void init(){
setTitle("客户端");
setLayout(new BorderLayout());
//连接服务器按钮单击事件
connServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
socket=new Socket("127.0.0.1",12345);
System.out.println("连接成功");
new receiverMsgThread().start();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//发送按钮单击事件
sendBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write(sendMessage.getText());
out.newLine();
out.flush();
System.out.println("222");
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//将组件添加到窗体中
JPanel panel=new JPanel();
panel.add(connServer);
panel.add(sendMessage);
panel.add(sendBtn);
add(allMessage,BorderLayout.CENTER);
add(panel,BorderLayout.SOUTH);
//配置窗体
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
class receiverMsgThread extends Thread{
public void run(){
InputStream is=null;
BufferedReader br=null;
String str=null;
try {
is=socket.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
while(true){
str=br.readLine()+"\n";
allMessage.append("服务器说:"+str);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("客户端");
}
}
public static void main(String[] args) {
new MyClientFrame();
}
}
程序运行界面如下:
目前为止,服务端只能与一个客户端进行通信。在编写的过程中,由于对BufferedReader类,之前并不了解,因此在编写的过程中,遇到了很大的问题,导致走了很多的弯路。最后通过查阅其文档,解决了问题。主要是因为其readLine()方法,在发送数据时,它是以回车符作为结束的,否则它不会结束,从而导致后续的操作无法完成,因此在发送数据时,一定要注意,代码如下:
out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));out.write(sendMessage.getText());//这个只是将数据写入到缓存中,并不真正进行发送
out.newLine();//这是一个新行,标识传输数据的结束,这点一定要注意
out.flush();//这个是将缓存中的数据进行发送
四、服务端的改进
以上程序代码中,服务器只能接收一个客户端的连接,下面对服务器端进行改进,实现多个客户端的连接。
思想如下:采用多线程方式,每一个客户端连接时,启动一个线程负责该客户端的通信,将产生的客户端Socket放入到一个集合中,然后,当客户端发送数据时,服务器端将收到的数据转发给所有的客户端。服务端修改后的代码如下;
package socket.demo2;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class MyServerFrame extends JFrame{
//保存客户端的Socket,用于向所有的客户端进行数据的转发。
private static List<Socket> clients=new ArrayList<Socket>();
//接收客户端发送的消息
private JTextArea allMessage=new JTextArea(8,20);
// 输入发送给客户端的消息
private JTextField sendMessage=new JTextField(20);
//消息发送按钮
private JButton sendBtn=new JButton("发送");
private JButton startServer=new JButton("开始服务器");
private ServerSocket serverSocket=null;//服务器端Socket
private BufferedReader in=null;//用于接收客户端发送的数据
private BufferedWriter out=null;//用于发送数据给客户端
private Socket socket=null;//客户端连接对象
private int port;
public void setPort(int port){
this.port=port;
}
public MyServerFrame(){
init();
}
private void init(){
setTitle("服务端");
setLayout(new BorderLayout());
//开始服务器按钮单击事件
startServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startServer.setEnabled(false);
//启动连接线程
try {
serverSocket=new ServerSocket(port);
} catch (IOException e1) {
e1.printStackTrace();
}
new connClient().start();
}
});
//发送按钮单击事件
sendBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
for(Socket s:clients){
out=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
out.write(sendMessage.getText());
out.newLine();
out.flush();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//将组件添加到窗体中
JPanel panel=new JPanel();
panel.add(startServer);
panel.add(sendMessage);
panel.add(sendBtn);
add(allMessage,BorderLayout.CENTER);
add(panel,BorderLayout.SOUTH);
//配置窗体
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
class connClient extends Thread{
public void run(){
while(true){
try {
socket=serverSocket.accept();
clients.add(socket);
new sendMsgToClients(socket).start();
new receiverMsgThread().start();//启动线程接收客户端数据
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
//接收信息线程
class receiverMsgThread extends Thread{
public void run(){
try {
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str=null;
while (true){
str=in.readLine()+"\n";
allMessage.append("客户端说:"+str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class sendMsgToClients extends Thread{
private Socket clientSocket;
public sendMsgToClients(Socket clientSocket){
this.clientSocket=clientSocket;
}
public void run(){
//首先接收客户端发送过来的信息,
//然后向客户端,进行信息的转发。
try {
while(true){
in=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String str=in.readLine();
for(Socket s:clients){
out=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
out.write(str);
out.newLine();
out.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
clients.remove(socket);
}
}
}
public static void main(String[] args) {
MyServerFrame myServerFrame=new MyServerFrame();
myServerFrame.setPort(12345);
}
}
以上是 JavaSocket网络编程 的全部内容, 来源链接: utcz.com/z/508883.html