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

最近网络结课刚好梳理一下所学的知识。
想要做一个网络聊天的程序,就要先知道需要用到什么知识和工具。

分享下别人写的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();
			}
		}
	}
}
最后效果展示:

基于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();
		}
	}
}


  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
基于TCPUDP聊天程序可以分为单向和双向两种实现方式。 1. 基于TCP的单向聊天室实现: TCP是面向连接的协议,因此在实现聊天室时需要先建立连接。单向聊天室指的是只有一个客户端向服务器发送消息,服务器将消息转发给所有客户端。具体实现步骤如下: - 服务器端: - 创建一个ServerSocket对象,指定端口号并监听客户端的连接请求。 - 当有客户端连接时,创建一个Socket对象,接收客户端发送的消息,并将消息转发给所有客户端。 - 客户端: - 创建一个Socket对象,指定服务器的IP地址和端口号。 - 向服务器发送消息。 2. 基于UDP的单向聊天室实现: UDP是无连接的协议,因此在实现聊天室时不需要建立连接。单向聊天室指的是只有一个客户端向服务器发送消息,服务器将消息转发给所有客户端。具体实现步骤如下: - 服务器端: - 创建一个DatagramSocket对象,指定端口号并监听客户端的连接请求。 - 当有客户端连接时,创建一个DatagramPacket对象,接收客户端发送的消息,并将消息转发给所有客户端。 - 客户端: - 创建一个DatagramSocket对象,指定服务器的IP地址和端口号。 - 向服务器发送消息。 3. 基于TCP的双向聊天室实现: 双向聊天室指的是客户端和服务器都可以发送和接收消息。具体实现步骤如下: - 服务器端: - 创建一个ServerSocket对象,指定端口号并监听客户端的连接请求。 - 当有客户端连接时,创建一个Socket对象,接收客户端发送的消息,并将消息转发给所有客户端。 - 客户端: - 创建一个Socket对象,指定服务器的IP地址和端口号。 - 创建一个线程用于发送消息,创建另一个线程用于接收消息。 4. 基于UDP的双向聊天室实现: 双向聊天室指的是客户端和服务器都可以发送和接收消息。具体实现步骤如下: - 服务器端: - 创建一个DatagramSocket对象,指定端口号并监听客户端的连接请求。 - 当有客户端连接时,创建一个DatagramPacket对象,接收客户端发送的消息,并将消息转发给所有客户端。 - 客户端: - 创建一个DatagramSocket对象,指定服务器的IP地址和端口号。 - 创建一个线程用于发送消息,创建另一个线程用于接收消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值