基于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();
}
}
}
}
最后效果展示:
基于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();
}
}
}
上一篇: 【Ngnix】ngnix定义、优点、配置文件结构、功能
下一篇: nginx 安装配置