</pre></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="white-space:pre"></span><span style="white-space:pre"> </span>-------</span><a target=_blank target="_blank" href="http://www.itheima.com/" style="text-align:center; font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="color:rgb(255,0,0)">android培训</span></a><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px">、</span><a target=_blank target="_blank" href="http://www.itheima.com/" style="text-align:center; font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="color:rgb(255,0,0)">java培训</span></a><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px">、</span><span style="text-align:center; color:rgb(53,53,53); font-family:Arial,Helvetica,simsun,u5b8bu4f53; line-height:25px">java学习型技术博客、期待与您交流!</span><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"> -</span><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"> ----------</span></span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px">接着昨天的UDP编程说起,说说理解中的Socket TCP编程:</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"></span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px">一、什么Socket?</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>JDK的描述:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。什么意思呢?可以这么说,网络上的两个程序通过一个<strong>双向的通讯连接实现数据的交换,</strong>这个双向链路的一段称为一个Socket(貌似网线的两头)。Socket通常用来实现客户端和服务端的连接。Socket是TCP/IP协议的一个一个编程界面,一个Socket有一个IP地址和一个端口号<strong>唯一</strong>的确定。</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"> 在Java中,Socket编程主要指的就是基于TCP/IP协议的网络编程。</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px">二、Socket通讯的过程</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>显然,由Socket定义知,有两方,一方为Server服务端,另一方为Client客户端,Server端监听某个端口是否有连接的请求,Client端负责向Server端发出连接的请求,Server在未连接之间一直处于阻塞accept状态,当监听到有Client的请求,并建立起了互信之后,Server和Client端就可以互相收发数据了,明显的<strong>Socket的传输和IO流是密不可分的</strong>!</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"> 从上面的阐述中,我们也可以看出建立一个完整的Socket,所要包含的步骤:</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>1) 创建Socekt;</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>2) 监听Client请求(<strong>Client端没有这一步骤,只针对Server</strong>)</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>3) 连接到Socket的输入/输出流;</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>4) 按照协议对Socket进行读/写操作</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>5) 关闭资源,也就是关闭Socket</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>网络上照了照片,能很好地说明这个通信过程,图片如下:</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><img src="https://img-my.csdn.net/uploads/201304/23/1366728416_1782.jpg" alt="" /></span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px">三、创建Socket</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>Java JDK 为Socket编程提供了两个类,ServerSocket和Socket,Socket前面已经说过了。ServerSocket是转么针对服务器而言的一个套接字。服务器套接字等待请求通过网络传入(前面所说的阻塞)。它基于该请求执行某些操作,然后可能想请求者返回结果。</span></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>ServerSocket 的主要构造方法有:</span></span></div><div style="text-align:left"><span style="font-size:14px"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"></span></span><table border="1" cellspacing="0" summary="" cellpadding="3" width="100%"><tbody><tr class="TableRowColor" bgcolor="white"><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">ServerSocket</a></strong>()</code> 创建非绑定服务器套接字。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">ServerSocket</a></strong>(int port)</code> 创建绑定到特定端口的服务器套接字。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">ServerSocket</a></strong>(int port, int backlog)</code> 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">ServerSocket</a></strong>(int port, int backlog,<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> bindAddr)</code> 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。</span></td></tr></tbody></table><span style="font-size:14px"></span></div><div style="text-align:left"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:14px"><span style="white-space:pre"></span>Socket的主要构造方法有:</span></span></div><div style="text-align:left"><span style="font-size:14px"><span style="text-align:center; color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"></span></span><table border="1" cellspacing="0" summary="" cellpadding="3" width="100%"><tbody><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>()</code> 通过系统默认类型的 SocketImpl 创建未连接套接字</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> address, int port)</code> 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> host, int port, boolean stream)</code> <strong>已过时。</strong> <em>Use DatagramSocket instead for UDP transport.</em></span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> address, int port,<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> localAddr, int localPort)</code> 创建一个套接字并将其连接到指定远程地址上的指定远程端口。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.net 中的类" href="">Proxy</a> proxy)</code> 创建一个未连接的套接字并指定代理类型(如果有),该代理不管其他设置如何都应被使用。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px">protected</span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.net 中的类" href="">SocketImpl</a> impl)</code> 使用用户指定的 SocketImpl 创建一个未连接 Socket。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.lang 中的类" href="">String</a> host, int port)</code> 创建一个流套接字并将其连接到指定主机上的指定端口号。</span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.lang 中的类" href="">String</a> host, int port, boolean stream)</code> <strong>已过时。</strong> <em>使用 DatagramSocket 取代 UDP 传输。</em></span></td></tr><tr class="TableRowColor" bgcolor="white"><td valign="top" width="1%" align="right"><span size="-1" style=""><code><span style="font-size:14px"> </span></code></span></td><td><span style="font-size:14px"><code><strong><a target=_blank target="_blank" href="">Socket</a></strong>(<a target=_blank target="_blank" title="java.lang 中的类" href="">String</a> host, int port,<a target=_blank target="_blank" title="java.net 中的类" href="">InetAddress</a> localAddr, int localPort)</code> <span style="background-color:rgb(255,255,255)"><span style="color:#cccccc"> </span><span style="color:#330033"> 创建一个套接字并将其连接到指定远程主机上的指定远程端口</span><span style="color:#cccccc">。</span></span></span></td></tr></tbody></table></div><div><span style="text-align:center"><span style="font-size:14px"><span style="background-color:rgb(255,255,255)"><span style="color:rgb(204,204,204); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px; white-space:pre"></span><span style="color:#330033"><span style="font-family:宋体; line-height:20px; white-space:pre">轻重adderess、host和port分别是双线连接中另一方的IP地址、主机名和端口号,</span><code style="line-height:20px; white-space:pre; font-family:宋体">stream</code><span style="font-family:宋体; line-height:20px; white-space:pre"> - 如果为 </span><code style="line-height:20px; white-space:pre; font-family:宋体">true</code><span style="font-family:宋体; line-height:20px; white-space:pre">,则创建流套接字;否则创建数据报套接字。</span><span style="font-family:SimSun"><span lang="EN-US" style="line-height:20px; white-space:pre; text-indent:32px">lo</span></span><span lang="EN-US" style="text-indent:32px">calPort</span><span style="text-indent:32px">表示本地主机的端口号,</span><span lang="EN-US" style="text-indent:32px">localAddr</span><span style="text-indent:32px">和</span><span lang="EN-US" style="text-indent:32px"> bindAddr</span><span style="text-indent:32px">是本地机器的地址(</span><span lang="EN-US" style="text-indent:32px">ServerSocket</span></span></span><span style="text-indent:32px"><span style="color:#330033; background-color:rgb(255,255,255)">的主机地址),<span lang="EN-US" style="text-indent:32px">impl</span><span style="text-indent:32px">是</span><span lang="EN-US" style="text-indent:32px">socket</span><span style="text-indent:32px">的父类,既可以用来创建</span><span lang="EN-US" style="text-indent:32px">serverSocket</span><span style="text-indent:32px">又可</span><span style="text-indent:32px"> </span><span style="text-indent:32px">以用来创建</span><span lang="EN-US" style="text-indent:32px">Socket</span><span style="text-indent:32px">。</span><span lang="EN-US" style="text-indent:32px">count</span><span style="text-indent:32px">则表示服务端所能支持的最大连接数。</span></span></span></span></span></div><div style="text-indent:0px"><span style="text-align:center"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px"><span style="white-space:pre"></span>例如:Socket client = new Socket("127.0.0.1",8000);</span></span></span></span></span></div><div style="text-indent:0px"><span style="text-align:center"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px"><span style="white-space:pre"></span> ServerSocket server = new ServerSocket(8000);</span></span></span></span></span></div><div><span style="text-align:center"><span style="text-indent:32px"><span style="text-indent:32px"><span style="font-size:14px"><span style="background-color:rgb(255,255,255)"><span style="white-space:pre"></span><strong>注意:</strong>在选择端口是,务必要小心。上一篇中介绍过每一个端口提过一种特定的服务,只有给出正确的的端口,才能进行互相连接,进行正常的数据传输,</span><span style="background-color:rgb(255,255,255)"><span lang="EN-US" style="text-indent:32px">0~1023</span><span style="text-indent:32px">的端口号为系统所保留,例如</span><span lang="EN-US" style="text-indent:32px">http</span><span style="text-indent:32px">服务的端口号为</span><span lang="EN-US" style="text-indent:32px">80,telnet</span><span style="text-indent:32px">服务的端口号为</span><span lang="EN-US" style="text-indent:32px">21,ftp</span><span style="text-indent:32px">服务的端口号为</span><span lang="EN-US" style="text-indent:32px">23, </span><span style="text-indent:32px">所以我们在选择端口号时,最好选择一个大于</span><span lang="EN-US" style="text-indent:32px">1023</span><span style="text-indent:32px">的数以防止发生冲突。</span></span></span></span></span></span></div><div><span style="text-align:center"><span style="text-indent:32px"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px"> 同时,socket会抛出异常,需要我们去捕获处理。</span></span></span></span></span></span></div><div><span style="text-align:center"><span style="text-indent:32px"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px">4、简单示例 </span></span></span></span></span></span></div><div><span style="text-align:center"><span style="text-indent:32px"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px"> 例子非常简单,不做过多说明,都有注释</span></span></span></span></span></span></div><div><span style="text-align:center"><span style="text-indent:32px"><span style="text-indent:32px"><span style="background-color:rgb(255,255,255)"><span style="text-indent:32px"><span style="font-size:14px"></span></span></span></span></span></span><pre name="code" class="java">/*
需求:建立一个文本转换服务器。、
客户端个服务端发送文本,服务端会将文本转成大写在返回给客户端。
而且客户端可以不断的进行文本转换,当客户端束缚over是,转换结束。
分析:
客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。
源:键盘录入
目的:网络输出流,网络设备。
而且操作的是文本数据。可以选择字符流。
步骤:
1、建立服务,
2、获取键盘录入
3、将数据发给服务端
4、获取返回的的大写数据
5、结束,关闭资源。
都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。
*/
import java.io.*;
import java.net.*;
class TransClient
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("127.0.0.1" , 10000);
//定义读取键盘数据的流对象
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//定义目的,将数据吸入到socket输出流,发给服务端
//BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
//定义一个socket读取流,读取服务端返回的大写信息。
BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = bufr.readLine())!= null)
{
if("over".equals(line))
break;
//bufout.write(line);
//bufout.newLine();
//bufout.flush();
out.println(line);
String str = bufin.readLine();
System.out.println("server:" + str);
}
bufr.close();
s.close();
}
}
/*
服务端:
源:socket读取流
目的:socket输出流
都是文本,装饰之。
*/
class TransServer
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"...connected");
//读取socket读取流中的数据。
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
//目的。socket输出流,将大写数据写入到socket输出流,并发送给客户端。
//BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream() , true);
String line = null;
while((line = bufIn.readLine())!=null)
{
System.out.println(line);
//bufOut.write(line.toUpperCase());
//bufOut.newLine();
//bufOut.flush();
out.println(line.toUpperCase());
}
s.close();
ss.close();
}
}
示例二:客户端向服务端上传文件
import java.io.*;
import java.net.*;
class TextClient
{
public static void main(String[] args) throws IOException
{
Socket s = new Socket("127.0.0.1",10000);
BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
/* DataOutputStream dos = new DataOutputStream(s.getOutputStream());
//long time = System.currentTimeMillis();
dos.write(time);
out.println(time);
*/
String line = null;
while((line = bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line);
}
s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = bufIn.readLine();
System.out.println(str);
bufr.close();
s.close();
}
}
class TextServer
{
public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...connected");
//DataInputStream dis
// DataInputStream dis = new DataInputStream(s.InputStream());
// long l = dis.readLong();
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true);
String line = null;
while((line = bufIn.readLine())!=null)
{
out.println(line);
}
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("上传成功。。。");
out.close();
s.close();
ss.close();
}
}
好了,其实很重要的一点事在连接通信过程中对流的处理,以及逻辑的判断是最重要的,因为格式都是一样的,所以中间数据的传输是最最重要的。