欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于TCP/UDP的网络聊天程序

程序员文章站 2022-07-08 19:50:40
...
最近网络结课刚好梳理一下所学的知识。
想要做一个网络聊天的程序,就要先知道需要用到什么知识和工具。

分享下别人写的Socket编程知识链接  Socket编程
基于TCP实现网络聊天1.0(无图形化界面):
服务器端Service:
/*服务器端*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class Service {
	public static void main(String args[]) 
	{
		ServerSocket serverSocket;     //创建ServerSocket服务对象
		System.out.println("------Server------");
		try {
			serverSocket=new ServerSocket(2046);   //在2046端口建立监听
			System.out.println("服务器监听建立,等待连接...");
			Socket socket=serverSocket.accept(); //产生阻塞直至客户端连接
			System.out.println("已成功连接!");
			Thread thread=new Thread(new Handler(socket));    //创建新线程
			thread.start();     //启动线程
			serverSocket.close();   //关闭服务
		}
		catch(SocketException e)
		{
			e.printStackTrace();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}
处理类Handler:
import java.net.Socket;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.IOException;

public class Handler implements Runnable {
	private Socket socket;
	Handler(Socket socket)
	{
		this.socket=socket;
	}
	public void run()
	{
		try {
			System.out.println("新连接:"+socket.getInetAddress()+":"+socket.getPort());
			InputStreamReader isr=new InputStreamReader(socket.getInputStream());
			BufferedReader br=new BufferedReader(isr);
			String words;
			while((words=br.readLine())!=null)
			{
				System.out.println("收到消息:"+words);
				Writer writer=new OutputStreamWriter(socket.getOutputStream());
				System.out.println("请输入回复:");
				Scanner sc=new Scanner(System.in);
				String content=sc.nextLine();
				writer.write(content+"\n");
				Thread.sleep(10000);
				writer.flush();
				sc.close();
			}		
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		finally 
		{
			try {
				System.out.println("关闭连接:"+socket.getInetAddress()+":"+socket.getPort());
				if(socket!=null)
				{
				socket.close();
				}
			}catch(IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}
客户端Client:
/*客户端*/
import java.net.Socket;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.Writer;
import java.io.BufferedReader;
import java.util.Scanner;
public class Client {
	public static String serverId="此处输入IP地址";
	public static void main(String args[])
	{
		System.out.println("------Client------");
		Socket socket;
		Scanner sc;
		try {
			socket=new Socket(serverId,2046); //建立连接
			System.out.println("连接已建立!");
			Writer writer=new OutputStreamWriter(socket.getOutputStream());
			System.out.println("请输入消息:");
			sc=new Scanner(System.in);
			String content=sc.nextLine();
			writer.write(content+"\n");
			writer.flush();
			System.out.println("消息已发出!");
			InputStreamReader isr=new InputStreamReader(socket.getInputStream());
			BufferedReader br=new BufferedReader(isr);
			System.out.println("收到消息:"+br.readLine());
			socket.close();
			}
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
}
ps:在运行过程中发现了服务器端没有响应的问题。
readLine()方法在进行读取一行时,只有遇到回车(\r)或者换行符(\n)才会返回读取结果,这就是“读取一行的意思”,重要的是readLine()返回的读取内容中并不包含换行符或者回车符;并且,当realLine()读取到的内容为空时,并不会返回 null,而是会一直阻塞,只有当读取的输入流发生错误或者被关闭时,readLine()方法才会返回null。

由于在客户端使用的readLine()来读取用户输入,所以当用户按下回车键是,readLine() 返回读取内容,但此时返回的内容并不包含换行符,而当在服务器端用readLine()再次读取时,由于读取的内容没有换行符,所以readLine()方法会一直阻塞等待换行符,这就是服务器端没有输出的原因。

解决方法:在客户端每次输入回车后,手动给输入内容加入"\n"或"\r",再写入服务器。



基于TCP实现网络聊天2.0(图形化界面):
/*客户端*/
import java.net.Socket;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.Writer;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Client extends JFrame {
	public static String serverId="输入IP地址";
	private static JTextField jip;        //IP地址
	private static JButton connect;       //连接按钮
	private static JTextArea ta;          //聊天区域
	private static JTextField text;       //输入消息
	private static JButton send;          //发送按钮
	private static JButton stop;          //停止服务按钮
	Socket socket;
	Client()
	{
		JFrame frame=new JFrame("网络聊天---客户端");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(600, 420);
		Container c=frame.getContentPane();
		c.setLayout(new FlowLayout()); 
		JTextField address=new JTextField("请输入要连接的IP:",20);
		jip=new JTextField("10.101.219.78",20);
		connect=new JButton("连接");
		connect.addActionListener(new ActionListener() //添加连接按钮监听事件
		{
			public void actionPerformed(ActionEvent e)
			{
				try
				{
					socket=new Socket(serverId,2046); //建立连接
					ta.append("连接已建立!");
				}
				catch(Exception ex)
				{
					ex.printStackTrace();
				}
			}
		});        
		ta=new JTextArea(15,52);    
		text=new JTextField(40);           
		send=new JButton("发送");     
		send.addActionListener(new ActionListener()   //添加发送按钮监听事件
		{
			public void actionPerformed(ActionEvent e)
			{
				try {
					Writer writer=new OutputStreamWriter(socket.getOutputStream());
					ta.append("请输入消息:"+"\n");
					String s=text.getText();
					ta.append("我:"+s+"\n");
					writer.write(s+"\n");
					writer.flush();
					ta.append("消息已发出!"+"\n");
					InputStreamReader isr=new InputStreamReader(socket.getInputStream());
					BufferedReader br=new BufferedReader(isr);
					ta.append("收到消息:"+br.readLine());
				}
				catch(Exception ex)
				{
					ex.printStackTrace();
				}
			}
		});        
		stop=new JButton("停止服务");
		stop.addActionListener(new ActionListener()    //添加停止服务按钮监听事件
		{
			public void actionPerformed(ActionEvent e)
			{
				try {
					socket.close();
					}
				catch(Exception ex) 
				{
					ex.printStackTrace();
				}		
			}
		});        
		c.add(address);
		c.add(jip);
		c.add(connect);
		c.add(ta);
		c.add(text);
		c.add(send);
		c.add(stop);
		frame.setVisible(true);
	}
	public static void main(String args[])
	{
		Client client=new Client();
		ta.append("请建立连接!");
	}
}
服务器:
/*服务器端*/
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Service extends JFrame{
	private static Service service=new Service();
	private static ServerSocket serverSocket;     //创建ServerSocket服务对象
	private static Socket socket;
	public static JTextArea ta;     //聊天区域
	public static JTextField text;  //消息输入
	public static JButton send;     //发送按钮
	Service()
	{
		JFrame frame=new JFrame("网络聊天---服务器");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(600, 400);
		Container c=frame.getContentPane();
		c.setLayout(new FlowLayout()); 
		ta=new JTextArea(15,52);     
		text=new JTextField(40);     
		send=new JButton("发送"); 
		send.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				try {
					Writer writer=new OutputStreamWriter(socket.getOutputStream());
					ta.append("请输入消息:"+"\n");
					String s=text.getText();
					ta.append("我:"+s+"\n");
					writer.write(s+"\n");
					writer.flush();
					ta.append("消息已发出!"+"\n");
				}
				catch(Exception ex)
				{
					ex.printStackTrace();
				}
			}
		});
		c.add(ta);
		c.add(text);
		c.add(send);
		frame.setVisible(true);
	}
	public static void main(String args[]) 
	{
		try {
			serverSocket=new ServerSocket(2048);   //在2046端口建立监听
			ta.append("服务器监听建立,等待连接..."+"\n");
			socket=serverSocket.accept(); //产生阻塞直至客户端连接
			ta.append("已成功连接!"+"\n");
			Thread thread=new Thread(new Handler(socket));    //创建新线程
			thread.start();     //启动线程
			serverSocket.close();   //关闭服务
		}
		catch(SocketException e)
		{
			e.printStackTrace();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}
处理器类:
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Handler implements Runnable {
	private Socket socket;
	Handler(Socket socket)
	{
		this.socket=socket;
	}
	public void run()
	{
		try {
			System.out.println("新连接:"+socket.getInetAddress()+":"+socket.getPort());
			InputStreamReader isr=new InputStreamReader(socket.getInputStream());
			BufferedReader br=new BufferedReader(isr);
			String words;
			while((words=br.readLine())!=null)
			{
				Service.ta.append("收到消息:"+words+"\n");
				Service.ta.append("请输入回复:"+"\n");
			}		
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		finally 
		{
			try {
				System.out.println("关闭连接:"+socket.getInetAddress()+":"+socket.getPort());
				if(socket!=null)
				{
				socket.close();
				}
			}catch(IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}
最后效果展示:
基于TCP/UDP的网络聊天程序
基于UDP实现网络聊天(无图形化界面):
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/*发送方*/
public class Send {
	public static void main(String args[])throws IOException
	{
		DatagramSocket ds1=new DatagramSocket();     //发送端口
		DatagramSocket ds2=new DatagramSocket(4000);  //接收端口
		int port=3000;     //端口号
		InetAddress IP=InetAddress.getByName("10.101.219.78");
		while(true)
		{
			Scanner sc=new Scanner(System.in);
			System.out.println("请输入发送内容:");
			String content=sc.nextLine();
			byte[] buffer=content.getBytes();
			int length=buffer.length;
			DatagramPacket dp1=new DatagramPacket(buffer,length,IP,port);
			ds1.send(dp1);
			byte[] buffer1=new byte[1024];   //接收
			int len=buffer1.length;
			DatagramPacket dp2=new DatagramPacket(buffer1,len);
			ds2.receive(dp2);
			byte[] words=dp2.getData();
			int leng=words.length;
			InetAddress address=dp2.getAddress();
			String ip=address.getHostAddress();
			System.out.println(ip+"说"+new String(words,0,leng));
		}	
			//sc.close();
			//ds1.close();
			//ds2.close();
	}
}

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/*接收方*/
public class Receive {
	public static void main(String args[])throws IOException
	{
		int port=4000;    //接收方给发送方的端口
		InetAddress IP=InetAddress.getByName("10.101.219.78");
		DatagramSocket ds1=new DatagramSocket(3000);     //接收端口
		DatagramSocket ds2=new DatagramSocket();   //发送端口端口
		
		while(true)
		{
			byte[] buffer1=new byte[1024];
		    int length=buffer1.length;
			DatagramPacket dp=new DatagramPacket(buffer1,length);
			ds1.receive(dp);
			byte[] words=dp.getData();
			int len=words.length;
			InetAddress address=dp.getAddress();
			String ip=address.getHostAddress();
			System.out.println(ip+"说"+new String(words,0,len));
			System.out.println("请输入回复消息:");
			Scanner sc=new Scanner(System.in);
			String content=sc.nextLine();
			byte[] buffer2=content.getBytes();
			int leng=buffer2.length;
			DatagramPacket dp1=new DatagramPacket(buffer2,leng,IP,port);
			ds2.send(dp1);
			System.out.println("发送成功!");
			//sc.close();
			//ds1.close();
			//ds2.close();
		}
	}
}