JavaSocket网络编程

coding

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

回到顶部