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

来源:互联网 发布:mac雪花高光粉饼试色 编辑:程序博客网 时间:2024/05/08 18:05
最近网络结课刚好梳理一下所学的知识。
想要做一个网络聊天的程序,就要先知道需要用到什么知识和工具。

分享下别人写的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();}}}