网络编程之TCP编程
- 网络编程之TCP编程
前面已经介绍过关于TCP协议的东西,这里不做赘述。Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生IO流来进行网络通信。说白了,玩基于Socket的网络编程无非就是使用ServerSocket创建一个服务器,然后使用socket进行通信,如果复杂一点呢,在加入多线程操作,用NIO代替IO来实现非阻塞Socket通信。
在很久以前我就听过一个前辈讲过,他说这个Socket翻译的很是别扭,叫做什么套接字,具体的不管了,反正他就叫这名字。那么关于这个套接字,要如何理解呢?一个Socket相当于一个电话机。OutputStream(输出)相当于话筒,InputStream(输入)相当于听筒。
服务器端要创建的对象:java.Net.ServerSocket。那么如何创建一个TCP服务器端程序呢?
1). 创建一个ServerSocket
2). 从ServerSocket接受客户连接请求
3). 创建一个服务线程处理新的连接
4). 在服务线程中,从socket中获得I/O流
5). 对I/O流进行读写操作,完成与客户的交互
6). 关闭I/O流
7). 关闭Socket
客户端要创建的对象:java.Net.Socket。那么如何创建一个TCP客户端程序呢?
1). 创建Socket
2). 获得I/O流
3). 对I/O流进行读写操作
4). 关闭I/O流
5). 关闭Socket
以下代码实现了一个服务器端和一个客户端:
import java.net.*;
import java.io.*; public class Server
{
public static void main(String[] args) throws IOException
{
// 创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
// 采用循环不断接受来自客户端的请求
while (true)
{
// 每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
// 将Socket对应的输出流包装成PrintStream
PrintStream ps = new PrintStream(s.getOutputStream());
// 进行普通IO操作
ps.println("您好,您收到了服务器的新年祝福!");
// 关闭输出流,关闭Socket
ps.close();
s.close();
}
}
}
import java.net.*;
import java.io.*; public class Client
{
public static void main(String[] args) throws IOException
{
Socket socket = new Socket("127.0.0.1", 30000);
// 将Socket对应的输入流包装成BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 进行普通IO操作
String line = br.readLine();
System.out.println("来自服务器的数据:" + line);
// 关闭输入流、socket
br.close();
socket.close();
}
}
上面的代码比较简单,当然我们可以加入多线程,这样子更加符合实际应用,因为前面的单线程很容易在IO流做读取操作的时候发生阻塞。下面的代码,服务器为每个socket单独启动一个线程,每条线程负责和一个客户端进行通信,客户端同样单独启动一个线程,该线程专门负责读取服务器数据。具体代码如下:
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.ArrayList; public class MyServer
{
//定义保存所有Socket的ArrayList
public static ArrayList<Socket> socketList = new ArrayList<Socket>(); public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(30000);
while (true)
{
// 此行代码会阻塞,将一直等待别人的连接
Socket s = ss.accept();
socketList.add(s);
// 每当客户端连接后启动一条ServerThread线程为该客户端服务
new Thread(new ServerThread(s)).start();
}
}
} class ServerThread implements Runnable
{
// 定义当前线程所处理的Socket
Socket s = null;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null; public ServerThread(Socket s) throws IOException
{
this.s = s;
// 初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
} public void run()
{
try
{
String content = null;
// 采用循环不断从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null)
{
// 遍历socketList中的每个Socket,
// 将读到的内容向每个Socket发送一次
for (Socket s : MyServer.socketList)
{
PrintStream ps = new PrintStream(s.getOutputStream());
System.out.println("这里是服务器。。。");
System.out.println(content);
ps.println(content);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
} // 定义读取客户端数据的方法
private String readFromClient()
{
String str = null;
try
{
str = br.readLine();
}
// 如果捕捉到异常,表明该Socket对应的客户端已经关闭
catch (Exception e)
{
// 删除该Socket。
MyServer.socketList.remove(s);
}
return str;
}
}
import java.io.*;
import java.net.*; public class MyClient
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("127.0.0.1", 30000);
// 客户端启动ClientThread线程不断读取来自服务器的数据
new Thread(new ClientThread(s)).start();
// 获取该Socket对应的输出流
PrintStream ps = new PrintStream(s.getOutputStream());
String line = null;
// 不断读取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while ((line = br.readLine()) != null)
{
// 将用户的键盘输入内容写入Socket对应的输出流
ps.println(line);
}
}
} class ClientThread implements Runnable
{
// 该线程负责处理的Socket
private Socket s;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null; public ClientThread(Socket s) throws IOException
{
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
} public void run()
{
try
{
String content = null;
// 不断读取Socket输入流中的内容,并将这些内容打印输出
while ((content = br.readLine()) != null)
{
System.out.println("这里是客户端。。。");
System.out.println(content);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
网络编程之TCP编程的更多相关文章
- [Python] 网络编程之TCP编程
转自:TCP编程 - 廖雪峰的官方网站 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协 ...
- 网络编程之UDP编程
网络编程之UDP编程 UDP协议是一种不可靠的网络协议,它在通信的2端各建立一个Socket,但是这个Socket之间并没有虚拟链路,这2个Socket只是发送和接受数据的对象,Java提供了Data ...
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
- java网络编程之TCP通讯
java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...
- 网络编程之TCP/IP各层详解
网络编程之TCP/IP各层详解 我们将应用层,表示层,会话层并作应用层,从TCP/IP五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议,就理解了整个物联网通信的原理. 首先,用户感知到的只 ...
- Java网络编程之TCP
Java网络编程之TCP TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建 ...
- C#网络程序设计(3)网络传输编程之TCP编程
网络传输编程指基于各种网络协议进行编程,包括TCP编程,UDP编程,P2P编程.本节介绍TCP编程. (1)TCP简介: TCP是TCP/IP体系中最重要的传输层协议,它提供全双工和可 ...
- 网络编程之TCP
知识补充:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字.其用于标识客户端请求的服务器和服务. TCP编程的实现步骤:服务器端:1.通过ServletSocket创建绑定到指定客户端 ...
随机推荐
- Appium dmg 安装:[TypeError: Cannot read property 'replace' of undefined]
问题原因:appium dmg 版本没有默认node.js 解决方案:安装稳定版的node.js.(官网下载安装即可.) 验证:命令行输入:node -v 查看版本号 npm -v 查看版本号
- SAP Cloud for Customer(C4C)和微信集成系列教程
这个系列主要从技术层面阐述了如何实现end user在微信app里发送的message能够投递到C4C系统,以及在C4C系统基于微信发送过来的message回复之后,如何将这些回复再push回微信ap ...
- wifipineapple插件:codeInject的使用
如果在中间人攻击的时候, 能在用户的网页中插入任意代码, 可以说已经完成一半了 wifipineapple有个codeInject插件, 可以让连上这个网络所有设备浏览网页的时候, 在网页中插入任意h ...
- AJAX的写法
AJAX可以说是前端开发必须要会的技术.AJAX是异步的javascript and xml.是他们技术的合称. 1.原生写ajax.很多小伙伴在会了jQuery后,将原生都忘记了,所以原生我还是要在 ...
- WPF 依赖属性源码 洞察微软如何实现DependencyProperty
依赖属性DependencyProperty是wpf最重要的一个类,理解该类如何实现对学习wpf帮助很大! 终于找到了该类的源码!仔细阅读源码,看看微软如何玩的花招! File: Base\Syste ...
- oracle练习--@余生请指教多
--1.查询出每个员工的编号,姓名,职位select Emp_id,Ename,job from emp;--2.查询每个员工的岗位名称select Ename,job from emp;--3.计算 ...
- Android基础_web通信3
在Android基础_web通信2中,我运用的JSONObject是Android原生的json类,通过import org.json.JSONObject来导入. 还有另外一种更简单的方法,就是用G ...
- 前端请求参数MD5加密校验,参数串解密
首先引入MD5加密库:=>https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js; 步骤:=>1.请求前对参数进行字典升序排序,排 ...
- TCP/IP和UDP之间的区别(转载)
在分析两者之间的区别之前,我们先搞清楚这两者的关系, TCP/IP协议簇 是一种网络控制协议,简单点说就是一种网络协议,我们网络中的计算机就是通过这套协议簇来进行数据通信的.这套协议簇里面包含了很多 ...
- MATLAB R2017a 安装与破解
第一步: 到我的百度网盘下载MatlAB2017a的原安装程序和破解补丁: 链接:https://pan.baidu.com/s/1jJz97DW 提取密码: d59m 第二步: 下载的两个iso文件 ...