您的当前位置:首页正文

网络实验6Socket编程实现聊天程序

来源:化拓教育网


南昌航空大学实验报告

课程名称: 计算机网络 实验名称: Socket编程实现聊天程序 班 级: 090451班 学生姓名: 杨 望 学号: 09045131 指导教师评定: 签 名:

一、

实验目的:

1、 掌握网络应用程序的开发方法;

2、 掌握Client/ Server结构软件的设计与开发方法 3、 掌握Socket机制的工作原理。

二、

实验题目:

使用Win32 Socket 函数实现聊天程序:能相互对发文本消息。

三、 服务端与客户端连接工作流程图:

开始 监听 有新客户端请 求连接服务器 不允许 允许连接? 提示错误信息 允许 建立连接 更新用户信息

四、收发消息工作流程图:

1

向客户端B 发送消息 监听 是 用户B在上线 ? 是用户B在忙碌 ? 是 用户B在隐身 ? 否发送给 用户B在离线? 客户端B 发送给服务器

五、 实验代码: 1、服务器端: package yuchen;

import java.io.BufferedReader; import java.io.IOException;

import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket;

import java.util.StringTokenizer; import java.util.Vector; public class ChatServer { static int port = 5566;//端口号 static Vector clients = new Vector(10);//存储连接客户信息 static ServerSocket server = null; //建立服务器socket static Socket socket = null; //套接字连接 public ChatServer() { try {System.out.println(\"Server start...\"); server = new ServerSocket(port); //初始化服务器套接字 while (true) { socket = server.accept(); //等待连接 System.out.println(socket.getInetAddress()+\"连接\\n\");//得到客户机地址 Client client = new Client(socket);

2

clients.add(client);//增加客户线程到向量中 client.start();//启动线程 notifyChatRoom(); //监视聊天室连接变化} } catch (Exception ex) { ex.printStackTrace();//输出出错信息}} public static void notifyChatRoom() { //监视客户端线程 StringBuffer newUser = new StringBuffer(\"newUser\"); for (int i = 0; i < clients.size(); i++) { Client c = (Client)clients.elementAt(i); newUser.append(\":\"+c.name); //客户端姓名字符串} sendClients(newUser);//发送信息到客户端} public static void sendClients(StringBuffer message) { for (int i= 0 ; i < clients.size(); i++) { Client client = (Client)clients.elementAt(i);//分别得到每个客户端的连接 client.send(message);//发送信息}} public void closeAll() { //关闭所有连接 while (clients.size() > 0 ) { //遍历整个Vector Client client = (Client) clients.firstElement(); //得到一个客户端 try {client.socket.close(); } catch(IOException ex) { ex.printStackTrace(); // 输出错误信息} clients.removeElement(client); //移出客户端}} public static void disconnect(Client c) {// 断开客户端 try {System.err.println(c.ip+\"断开连接\\n\"); } catch (Exception ex) { ex.printStackTrace();} clients.removeElement(c); c.socket = null;}

public static void main(String[] args) { new ChatServer();} class Client extends Thread { Socket socket;//连接端口 String name ;//用户姓名 String ip; //客户端ip地址 BufferedReader reader;//输入流 PrintStream ps;//输出流 public Client(Socket s) {socket = s; try {reader = new BufferedReader(new InputStreamReader(s.getInputStream())); ps = new PrintStream(s.getOutputStream());//得到输出流 String info = reader.readLine();//读取接收到的信息 StringTokenizer stinfo = new StringTokenizer(info,\":\"); //分解字符串 String head = stinfo.nextToken(); //获取关键字 System.out.println(stinfo.toString()); System.out.println(head);

3

if (stinfo.hasMoreTokens()){ name = stinfo.nextToken() ;//获取用户名} if (stinfo.hasMoreTokens()) { ip = stinfo.nextToken(); //获取IP地址} } catch (IOException ex) { ex.printStackTrace();} System.out.println(name); System.out.println(ip); } public void send (StringBuffer msg) { ps.println(msg); //输出信息 ps.flush();} public void run() { while (true) { String line = null; try {line = reader.readLine(); System.out.println(\"line:\"+line); } catch (IOException ex) { ex.printStackTrace(); //输出错误信息 ChatServer.disconnect(this);//断开连接 ChatServer.notifyChatRoom();//更新信息 return ; } if (line == null) { //客户离开 ChatServer.disconnect(this); ChatServer.notifyChatRoom(); return ;} StringTokenizer st = new StringTokenizer(line,\":\");//分解字符串 String keyword = st.nextToken(); if (keyword.equals(\"MSG\")) { //发送来的聊天信息 StringBuffer msg = new StringBuffer(\"MSG:\"); msg.append(name); //在信息上增加用户名 msg.append(st.nextToken(\"\\0\\n\")); ChatServer.sendClients(msg);//发送聊天语句到各个客户端 System.out.println(msg); } else if (keyword.equals(\"quit\")) { //退出命令 ChatServer.disconnect(this); //断开连接 ChatServer.notifyChatRoom(); //刷新信息}}}}} 2、客户端:package yuchen; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Label; import java.awt.TextArea; import java.awt.TextField;

import java.awt.event.ActionEvent;

4

import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException;

import java.io.InputStreamReader; import java.io.PrintStream; import java.net.InetAddress; import java.net.Socket;

import java.util.StringTokenizer; import javax.swing.JFrame;

import javax.swing.JOptionPane; import javax.swing.JPanel;

public class ChatClient extends JFrame implements ActionListener ,Runnable TextField tfName = new TextField(15);//姓名输入文本域 Button btConnect = new Button(\"连接\");//连接按钮 Button btDisconnect = new Button(\"断开连接\");//断开连接按钮 TextArea tfChat = new TextArea(8,27);//显示聊天信息文本域 Button btSend = new Button(\"发送\"); TextField tfMessage = new TextField(30);//聊天输入 java.awt.List list1 = new java.awt.List(9);//显示在线用户信息 Socket socket = null;//连接端口 PrintStream ps = null;//输出流 Listen listen = null; class Listen extends Thread { BufferedReader reader; PrintStream ps; String cname; Socket socket; ChatClient chatClient; public Listen(ChatClient client,String name,Socket socket) { try {this.chatClient = client; this.socket = socket; this.cname = name; reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); ps = new PrintStream(socket.getOutputStream()); } catch (IOException e) { e.printStackTrace();}} public void run() { while (true) { String line=null ; try { line = reader.readLine(); //读取数据流 System.out.println(\"客户端:\"+line);}catch (IOException ex) { ex.printStackTrace(); ps.println(\"quit\");; //断开连接

5

return;} StringTokenizer stinfo = new StringTokenizer(line,\":\"); //分解字符串 String keyword = stinfo.nextToken(); if (keyword.equals(\"MSG\")) { chatClient.tfChat.append(line+\"\\n\");} else if (keyword.equals(\"newUser\")){ chatClient.list1.clear(); chatClient.list1.add(\"users\ int i = 1; while (stinfo.hasMoreTokens()) { chatClient.list1.add(stinfo.nextToken(), i++);}}} }} public void actionPerformed(ActionEvent e) { try{if(e.getSource()==btConnect) { //点击连接按钮 if (socket == null) { socket = new Socket(InetAddress.getLocalHost(),5566); ps = new PrintStream(socket.getOutputStream());//获取输出流,写入信息 StringBuffer info = new StringBuffer(\"info:\"); String userinfo = tfName.getText()+\":\"+InetAddress.getLocalHost().toString(); ps.println(info.append(userinfo));//输出信息 ps.flush(); listen = new Listen(this,tfName.getText(),socket); listen.start();} } else if (e.getSource() == btDisconnect) { //点击断开连接按钮 disconnect(); } else if (e.getSource() == btSend) { //点击发送按钮 if (socket != null) { StringBuffer msg = new StringBuffer(\"MSG:\"); String msgtxt = new String(tfMessage.getText()); ps.println(msg.append(msgtxt));//发送信息 ps.flush(); } else { JOptionPane.showMessageDialog(this, \"请先连接!\\"提示\1);}}} catch (Exception ex) { ex.printStackTrace();//输出错误信息 }} public void disconnect() { //断开连接方法 if (socket != null) { ps.println(\"quit\");//发送信息 ps.flush(); socket = null; tfName.setText(\"\");}} public ChatClient(Socket socket) { this.setLayout(new BorderLayout()); JPanel panel1 = new JPanel(); Label label = new Label(\"姓名\");

6

panel1.setBackground(Color.orange); panel1.add(label); panel1.add(tfName); panel1.add(btConnect); panel1.add(btDisconnect); this.add(panel1,BorderLayout.NORTH); JPanel panel2 = new JPanel(); panel2.add(tfChat); panel2.add(list1); this.add(panel2,BorderLayout.CENTER); JPanel panel3 = new JPanel(); Label label2 = new Label(\"聊天信息\"); panel3.add(label2); panel3.add(tfMessage); panel3.add(btSend); this.add(panel3,BorderLayout.SOUTH); this.setBounds(50,50,400,350); this.setVisible(true); btConnect.addActionListener(this); btDisconnect.addActionListener(this); btSend.addActionListener(this); } public static void main(String[] args) { ChatClient client = new ChatClient(new Socket()); System.out.println(client.socket);}}} 六、 实验结果:

下面是杨和望的聊天记录:

7

七、 实验小结:

通过本次实验更好的掌握TCP和UDP网络编程。了解URL编程。掌握网络应用程序的开发方法;掌握Client/ Server结构软件的设计与开发方法掌握Socket机制的工作原理最后对于Java网络编程的知识有了更好的理解。

8

因篇幅问题不能全部显示,请点此查看更多更全内容