Java网络编程之TCP
Java网络编程之TCP
TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建,参数指定端口,如下:
Socket socket = new Socket("localhost",8888);//Client.java客户端
ServerSocket serverSocket = new ServerSocket(8888);//Server.java服务器端
//服务器ip为本机,端口为8888
我的想法:要实现单聊和群聊,首先,我得为标识每个客户端,我选择姓名,这样每个用户都知道是谁发的消息,那么,我需要每个姓名对应一个客户端Socket,用map存储
废话不多说,直接上代码:
1. 客户端:
```java
public class TcpClient {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名》》");
String userName = scanner.next();
Socket socket = new Socket("localhost",8888);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(userName);
new Thread(new SendMsg(socket)).start();
new Thread(new ReceiveMsg(socket)).start();
}
}
```
2. 客户端发送消息线程:
public class SendMsg implements Runnable{
private Socket socket;
public SendMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while(true) {
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
String[] msg = buffer.readLine().split("@");
MessageBean messageBean = new MessageBean(msg[0],msg[1]);
// DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// out.writeUTF(msg);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(messageBean);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 客户端接收消息线程:
public class ReceiveMsg implements Runnable{
private Socket socket;
public ReceiveMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while(true) {
DataInputStream in = new DataInputStream(socket.getInputStream());
System.out.println(in.readUTF());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 服务器端:
public class TcpServer {
public static void main(String[] args) throws Exception {
try {
//List<Socket> sockets = new ArrayList<>();
Map<String,Socket> map = new HashMap<>();
ServerSocket serverSocket = new ServerSocket(8888);
while(true) {
Socket socket = serverSocket.accept();
//服务器第一次接收到的信息一定是用户名
DataInputStream in = new DataInputStream(socket.getInputStream());
String username = in.readUTF();
synchronized (map) {
map.put(username, socket);
}
//能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果
// synchronized (sockets) {
// sockets.add(socket);
// }
new Thread(new ServerHandler(socket,map)).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 服务器处理事务线程端:
public class ServerHandler implements Runnable {
private Socket socket;
private Map<String, Socket> map;
public ServerHandler(Socket socket,Map<String, Socket> map) {
this.socket = socket;
this.map = map;
}
public String findKey(Map<String, Socket> map,Socket socket) {
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
if (map.get(key).equals(socket)) return key;
}
return null;
}
@Override
public void run() {
InetAddress address = socket.getInetAddress();
String ip = address.getHostAddress();
String username = findKey(map, socket);
System.out.println("ip为"+ip+"的"+username+":上线了----");
try {
while(true) {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
MessageBean messageBean = (MessageBean) in.readObject();
String msg = messageBean.getMsg();
String toPerson = messageBean.getToPerson();
if ("all".equals(toPerson)) {
//群聊
msg = username+":"+msg;
for(String key : map.keySet()){
if (username.equals(key)) {
continue;
}
DataOutputStream out = new DataOutputStream(map.get(key).getOutputStream());
out.writeUTF(msg);
}
}else {
//私聊
if (map.get(toPerson) == null) {
DataOutputStream out = new DataOutputStream(map.get(username).getOutputStream());
out.writeUTF("抱歉,"+toPerson+"不在线。。。。");
}else {
msg = username+"对您私聊说:"+msg;
DataOutputStream out = new DataOutputStream(map.get(toPerson).getOutputStream());
out.writeUTF(msg);
}
}
}
} catch (Exception e) {
//e.printStackTrace();
System.out.println(username+"下线了。。。。。");
synchronized (map) {
map.remove(username, socket);
}
}
}
}
6. 消息体类:
public class MessageBean implements Serializable{
private String msg;
private String toPerson;
public MessageBean() {
}
public MessageBean(String msg,String toPerson) {
this.msg = msg;
this.toPerson = toPerson;
}
public String getMsg() {
return msg;
}
public String getToPerson() {
return toPerson;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setToPerson(String toPerson) {
this.toPerson = toPerson;
}
}
运行结果:
Java网络编程之TCP的更多相关文章
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- java网络编程之TCP通讯
java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...
- Java网络编程之TCP通信
一.概述 Socket类是Java执行客户端TCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信.Socket类的方法会建立和销毁连接,设置各种Socket选项. Server ...
- java 网络编程之TCP通信和简单的文件上传功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- 4.Java网络编程之TCP/UDP
常见传输协议: UDP , TCP UDP协议: 特点: 1.将数据及源和目的封装成数据包中,不需要建立连接 2.每个数据包的大小限制在64K内 ...
- java网络编程之TCP实例
Dgram类 package Socket; import java.net.DatagramPacket; import java.net.InetAddress; public class Dgr ...
- 网络编程之TCP编程
网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...
- Java网络编程之InetAddress浅析
Java网络编程之InetAddress浅析 一.InetAddress综述 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetA ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
随机推荐
- 虚拟机安装的kali操作系统实现共享文件夹
虚拟机共享文件夹设置. 1.[虚拟机]-->[设置] 2.先在本地新建一个共享文件夹,然后将此文件夹的路径添加到虚拟机 3.进入kali操作系统,运行命令sudo vmhgfs-fuse .ho ...
- Unity3D学习笔记3——Unity Shader的初步使用
目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...
- .NET5控制台程序使用EF连接MYSQL
.NET5控制台程序使用EF连接MYSQL 1.使用nuget下载: Microsoft.Extensions.Configuration.Json Pomelo.EntityFrameworkCor ...
- 3个月零基础入门Python+数据分析,详细时间表+计划表分享
大家好,我是白云. 今天想给大家分享的是三个月零基础入门数据分析学习计划.有小伙伴可能会说,英语好像有点不太好,要怎么办?所以今天我给大家分享的资源呢就是对国内的小伙伴很友好,还附赠大家一份三个月学 ...
- RHCSA_DAY04
软连接与硬连接 Linux中的链接文件类似于windows中的快捷方式 软连接特点:软连接可以跨分区,可以对目录进行链接,源文件删除后,链接文件不可用 软连接命令格式:ln -s 源文件路径 目标路 ...
- python UI自动化之鼠标事件
使用 pyautogui 模块:import pyautogui 1. 鼠标移动至:1629,875是电脑屏幕坐标:0.25是移动时间 pyautogui.moveTo(1629,875, durat ...
- Android开发失业六个月了,无限的焦虑
最近到网上看到这样一个帖子: Android开发,坐标魔都:目前为止已经失业六个月,找工作期间,尤其是最近两天确实心态不好.要么没有面试,要么给的工资不符合预期( hr 压价太狠了,原先说的 19k, ...
- 获取元素在页面中位置 getBoundingClientRect()
DOM 原生方法getBoundingClientRect()获取元素相对视口位置 DOMRect 对象包含了一组用于描述边框的只读属性--left.top.right和bottom,单位为像素.除了 ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.B)- FlexSPI NOR连接方式大全(RT1160/1170)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT1160/1170两款MCU的FlexSPI NOR启动的连接方式. 这个 i.MXRT FlexSPI NOR 启动 ...
- Postman API 接口测试、Jenkin 持续集成测试
Postman 是一个创建和使用API的应用,Postman 对于Web开发者来说非常有用,Postman 带来的便利有很多,诸如: RESTFul接口测试不依赖其他端,进度不受影响 测试脚本即文档, ...