输出流共享到集合中,服务端遍历集合来广播输出流给客户端,来达到聊天室的功能.

课后作业:使用Mapk来实现@xxx 时,发送私聊内容给对方

Client

package chat;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import java.net.Socket;

import java.util.Scanner;

/**

* 聊天室客户端

* @author Administrator

*

*/

publicclassClient {

/*

* java.net.Socket

* 封装了TCP协议,使用它就可以基于TCP协议进行网络通讯

* Socket是运行在客户端的

*/

private Socket socket;

/**

* 构造方法,用来初始化客户端

* 实例化Socket的时候需要传入两个参数:

* 1.服务端地址:通过IP地址可以找到服务端的计算机.

* 2.服务端端口:通过端口可以找到服务端计算机上的服务端应用程序

* 实例化Socket的过程就是连接的过程,若远端计算机没有响应会抛出异常.

*/

public Client() throws Exception{

System.out.println("正在连接服务端...");

socket =new Socket("localhost", 8088);

System.out.println("已与服务端建立连接!");

}

/**

* 启动客户端

*/

publicvoid start(){

try {

Scanner scan =new Scanner(System.in);

/*

* 先要求用户输入一个昵称

*/

String nickName =null;

while(true){

System.out.println("请输入昵称:");

nickName = scan.nextLine();

if(nickName.length() >0){

break;

}

System.out.println("输入有误!");

}

System.out.println("欢迎你,"+ nickName +"!开始聊天吧!");

/*

* Socket提供的方法:

* OutputStream getOutputStream()

* 获取一个字节输出流,通过该流写出的数据会被发送至远端计算机.

*/

OutputStream out = socket.getOutputStream();

OutputStreamWriter osw =new OutputStreamWriter(out, "UTF-8");  //转换流,指定字符集

PrintWriter pw =new PrintWriter(osw, true);    //自动行刷新

/*

* 先将昵称发送给服务器

*/

pw.println(nickName);

/*

* 启动读取服务端发送过来消息的线程

*/

ServerHandler handler =new ServerHandler();

Thread t =new Thread(handler);

t.start();

/*

* 将字符串发送至服务端

*/

//          System.out.println("输入内容:");

while(true){

pw.println(scan.nextLine());

}

} catch (Exception e) {

e.printStackTrace();

}

}

publicstaticvoid main(String[] args) {

try {

Client client =new Client();

client.start();

} catch (Exception e) {

e.printStackTrace();

System.out.println("客户端启动失败!");

}

}

/**

* 该线程用来读取服务端发送过来的消息并输出到客户端控制台

* @author Administrator

*

*/

classServerHandlerimplements Runnable{

publicvoid run(){

try {

InputStream is = socket.getInputStream();

InputStreamReader isr =new InputStreamReader(is, "UTF-8");

BufferedReader br =new BufferedReader(isr);

String message =null;

while((message = br.readLine()) !=null){

System.out.println(message);

}

} catch (Exception e) {

}

}

}

}

Server

package chat;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.ArrayList;

import java.util.List;

/**

* 聊天室服务端

* @author Administrator

*

*/

publicclassServer {

/*

* 运行在服务端的ServerSocket主要负责:

* 1.向系统申请服务端口

*  客户端就是通过这个端口与之连接

* 2.监听申请的服务端口,当一个客户端通过该端口尝试连接时,

*  ServerSocket会在服务端创建一个Socket与客户端建立连接.

*/

private ServerSocket server;

/*

* 保存所有客户端输出流的集合

*/

private List<< span="">PrintWriter> allOut;

/**

* 用来初始化服务端

*/

public Server() throws Exception {

/*

* 初始化的同时申请服务端口

*/

server =new ServerSocket(8088);

allOut =new ArrayList<< span="">PrintWriter>();

}

/**

* 将给定的输出流存入共享集合

* @param out

*/

privatesynchronizedvoid addOut(PrintWriter out){

allOut.add(out);

}

/**

* 将给定的输出流从共享集合中删除

* @param out

*/

privatesynchronizedvoid removeOut(PrintWriter out){

allOut.remove(out);

}

/**

* 将给定消息发送给所有客户端

* @param message

*/

privatesynchronizedvoid sendMessage(String message){

for(PrintWriter out : allOut){

out.println(message);

}

}

/**

* 服务端开始工作的方法

*/

publicvoid start() {

try {

/*

* ServrSocket的accept方法是一个阻塞方法,作用是监听服务端口,

* 直到一个客户端连接并创建一个Socket,使用该Socket即可与刚连接的客户端进行交互.

*/

while(true){

System.out.println("等待客户端连接...");

Socket socket = server.accept();

System.out.println("一个客户端连接了!");

/*

* 启动一个线程,来完成与该客户端的交互

*/

ClientHandler handler =new ClientHandler(socket);

Thread t =new Thread(handler);

t.start();

}

} catch (Exception e) {

e.printStackTrace();

}

}

publicstaticvoid main(String[] args) {

try {

Server server =new Server();

server.start();

} catch (Exception e) {

e.printStackTrace();

System.out.println("服务端启动失败!");

}

}

/*

* 该线程负责处理一个客户端的交互

*/

classClientHandlerimplements Runnable{

/*

* 该线程处理的客户端的Socket

*/

private Socket socket;

/*

* 客户端该用户的昵称

*/

privateString nickName;

//客户端的地址信息

privateString host;

public ClientHandler(Socket socket){

this.socket = socket;

/*

* 通过Socket可以获取远端计算机的地址信息.

*/

InetAddress address = socket.getInetAddress();

//获取IP地址

host = address.getHostAddress();

}

publicvoid run(){

PrintWriter pw =null;

try {

/*

* Socket提供的方法

* InputStream getInputStream()

* 该方法可以获取一个输入流,从该流读取的数据就是从远端计算机发送过来的

*/

InputStream in = socket.getInputStream();

InputStreamReader isr =new InputStreamReader(in, "UTF-8");

BufferedReader br =new BufferedReader(isr);

/*

* 首先读取一行字符串为昵称

*/

nickName = br.readLine();

sendMessage(nickName +"上线了");

/*

* 通过Socket创建输出流用于将消息发送给客户端

*/

OutputStream os = socket.getOutputStream();

OutputStreamWriter osw =new OutputStreamWriter(os, "UTF-8");

pw =new PrintWriter(osw, true);

/*

* 将该客户端的输出流存入到共享集合中

*/

addOut(pw);

String message =null;

/*

* br.readLine() 在读取客户端发送过来的消息时,由于客户端断线,而其操作系统的不同,这里读取后的结果不同:

* 当windows的客户端断开时:br.readLine会抛出一场

* 当linux的客户端断开时:br.readLine会返回null

*/

while((message = br.readLine()) !=null){   //readLine() 读到文件末尾会返回null

//                  System.out.println(host + "说:" + message);

//                  pw.println(host + "说:" + message); //将客户端发送过来的消息返回给客户端,客户端去读Socket

//广播消息

sendMessage(nickName +"说:"+ message);

}

}catch (Exception e) {

e.printStackTrace();

} finally{

/*

* 处理当前客户端断开后的逻辑

*/

//将该客户端的输出流从共享集合中删除

removeOut(pw);

sendMessage(nickName +"下线了!");

try {

socket.close(); //Socket断开连接时,会自动关闭流

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

tcp通信程序发送图片_Unit11:TCP通信、wechat小程序相关推荐

  1. uni微信小程序 下载图片跟文字_微信小程序:图片与文字无法居中 最后解决的方法是——...

    最近做小程序,需要用到flex布局,发现垂直居中是用:vertical-align:middle或者line-height 后来发现这2个都不能完全实现图片与文字居中,这可怎么办? 大图片 我给sta ...

  2. 小程序mpvue图片绘制水印_mpvue开发小程序如何使用腾讯官方小程序插件--地图

    附带demo,码云地址 官方地图插件是有问题的,建议直接使用微信内置地图查看位置 //直接click调用 openMap() { let mapInfo = { startLat: 121.6695, ...

  3. 小程序背景图片从服务器获取,微信小程序button控件去边框、加背景图

    button边框去除 相信大家开发微信小程序时使用button会遇到一些与预期效果不同的样式问题.例如button的边框无法去除,在为button设置圆角的时候周围会有一些"杂质" ...

  4. 图片上传成功但是图片显示不出来_小程序上传图片到腾讯云

    这是小程序开发第二篇,主要介绍如何上传图片到腾讯云,之所以选择腾讯云,是因为腾讯云免费空间大 准备工作 上传图片主要是将图片上传到腾讯云对象存储(COS). 要使用对象存储 API,需要先执行以下步骤 ...

  5. 微信公众号发送小程序卡片_微信公众号里怎么添加小程序-如何在微信[[公众号]]添加小程序卡片-微信关联小程序...

    参考官方Demo 1.进入公众号,选择「关联小程序」后,微信公众号运营者用手机扫码进行认证,并输入小程序的AppID即可. 2.腾讯地图+小程序appID:wx7643d5f831302ab0 3. ...

  6. 通过图片识别定位拍摄地点——微信小程序

    原理--元数据 通过提取jpg格式图片中携带的元数据获得gps的信息,再通过调用地图openApi将经纬信息反解析为对应的实际地理位置. 测试小程序在这里 必备工具 1.微信小程序的云函数 2.腾讯地 ...

  7. Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)

    ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...

  8. 【微信小程序 - 工作实战分享】1.微信小程序发送手机短信验证码(阿里云)

    发送手机短信验证码 前言 一. 准备工作 二. 配置 三. 实战代码(仅仅是后台代码,前端传入手机号) 总结 前言 在网站和移动应用中利用短信验证码进行信息确认是最常用的验证手段.随着短信验证码的技术 ...

  9. 【Python发送短信验证码并与小程序对接】

    Python发送手机验证码流程 1.小程序端校验手机号格式 使用正则校验: 下面代码实现的是校验的是手机号必须是1开头的,然后第二位必须是3~9中间的某一个,然后剩下的九位必须是数字 这样其实就基本排 ...

最新文章

  1. PHP中redis的使用
  2. Python抓取网页数据的终极办法
  3. C语言之连接Mysql数据篇
  4. PHP操作Memcache实例介绍
  5. java tutorial mobi_Java 初学者List集合教程
  6. 4. Javascript 函数
  7. jenkins根据已打包的镜像,自动生成正式镜像
  8. 什么是 1号信令、7号信令和PRI信令?
  9. Yasm的作用及NASM详解
  10. C#调用第三方dll生成exe被dep拦截
  11. 云原生究竟怎么落地?
  12. 2019最新微信墙微信上墙微信弹幕婚庆会议大屏幕3D签到抽奖摇一摇微信上墙
  13. QGC地面站配置PX4Flow光流传感器
  14. 记录mumu模拟器AMD SVM(VT)开启失败的问题
  15. 序列化和反序列化的概念及应用
  16. matlab中ARCH效应检验步骤,请教一下各位大神!如何判断ARCH效应(附ARCH-LM检验结果)...
  17. macOS实现词典正常查询维基百科
  18. react-emotion_如何使用Web Speech API和Node.js构建语音转Emotion Converter
  19. 加入计算机网络协会申请书,协会申请书.doc
  20. 奇葩公司规定程序员工资按代码行数算工资,个个提成这么高?

热门文章

  1. C#.NET验证码智能识别学习笔记---02-C#.Net中Using关键字的用法
  2. 9W人脸清洗的问题--20170208
  3. 杭电2897邂逅明下邂逅明下
  4. android开发之AsyncTask的用法
  5. java 中的jframe_java中JFrame是什么
  6. python编程(反汇编)
  7. visio防火墙可以连接什么_画流程图,就是要用Visio软件!
  8. android 图片按钮变形,android wrap_content引起的图片变形
  9. SimpleDateFormat的parse与format的用法区别
  10. 我的世界服务器自定义代码,《我的世界》服务器指令代码秘籍大全