黑马程序员---网络编程(TCP传输)

来源:互联网 发布:天金加银软件下载 编辑:程序博客网 时间:2024/05/01 15:36

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

简介
UDP分为发送端和接受端
TCP分为客户端和服务器端(Socket和ServerSocket)
建立连接后
TCP三次握手的过程如下:
客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。

下面演示TCP传输的客户端和服务器端的互访
客户端发送数据给服务器端,服务器端接受数据后给客户端反馈信息

服务器端

package fourth;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** *服务器端: *1.创建服务器端的Socket服务,ServerSocket,并监听一个端口 *2.获取连接过来的客户端对象,通过ServerSocket的accept完成,这个方法是阻塞式的,如果没有连接就等待 *3.客户端如果发送过来数据,那么服务器端要使用对应的客户端对象,并获取到该客户端对象的读取流来获取数据 *4.关闭服务器(可选操作) * *定义服务器端,接受数据并打印在控制台上 */public class TcpServer2 {    public static void main(String[] args) {        try {            //建立服务端的Socket服务,并监听一个端口            ServerSocket ss=new ServerSocket(10004);            //通过accept获取客户端的发送数据            Socket s=ss.accept();            String ip=s.getInetAddress().getHostAddress();            System.out.println(ip+".....connected");            //获取数据            InputStream is=s.getInputStream();            OutputStream out=s.getOutputStream();            byte[]b=new byte[1024];            int len=is.read(b);            System.out.println(new String(b,0,len));            out.write("收到了,".getBytes());            s.close();//结束连接            ss.close();//可选的        } catch (IOException e) {            e.printStackTrace();        }    }}

客户端

package fourth;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;/** *客户端: *给服务器端发送一个文本数据 *1.创建Socket服务,并指定要连接的主机和端口 *2.获取Socket服务中的输出流,将数据写到流中,通过网络发送给服务器 *3.获取Socket服务中的输入流,获取服务器的反馈数据并打印 *4,关闭资源 * */public class TcpClient2 {    public static void main(String[] args) {        try {            //创建Socket服务,并指定要连接的主机和端口            Socket s=new Socket(InetAddress.getLocalHost(), 10004);            //为了发送数据,应该获得Socket流中的输出流            OutputStream out=s.getOutputStream();            out.write("Hello TCPClient".getBytes());            InputStream is=s.getInputStream();            byte[]b=new byte[1024];            int len=is.read(b);            System.out.println(new String(b,0,len));            s.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

注:一定要先启动服务器端,不然先启动客户端会报java.net.ConnectException异常

下面这个练习实现了服务器端的文本转换功能,把客户端的文本数据转成大写在返回
服务器端

package fourth;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;/** *需求:建立一个文本转换服务器 *客户端给服务器端发送文本,服务器端把文本转换为大写返回给客户端 *而且客户端可以不断进行文本转换,当客户端输入over时结束 * *分析 *客户端: *既然是在设备上操作数据,就可以用IO技术,并按照IO的操作规则来思考 *源:键盘录入 *目的:网络设备,网络输出流 *操作的是文本数据,可以使用字节流,同时提高效率加入缓冲 *服务器端 *源:Socket读取流 *目的:Socket输出流 *都是文本, */public class TransServer {    public static void main(String[] args) {        try {            ServerSocket ss=new ServerSocket(10005);            Socket s=ss.accept();            //读取Socket流中的数据            BufferedReader brIn=new BufferedReader(                    new InputStreamReader(s.getInputStream()));            //目的,Socket输出流,将大写数据写入到Socket输出流发送给客户端//          BufferedWriter bwOut=new BufferedWriter(//                  new OutputStreamWriter(s.getOutputStream()));            PrintWriter out=new PrintWriter(s.getOutputStream(),true);            String line=null;            while((line=brIn.readLine())!=null){//              bwOut.write(line.toUpperCase());//              bwOut.newLine();//              bwOut.flush();                out.println(line);            }            s.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

客户端

package fourth;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;/** * *步骤 *1.建立服务 *2.获取键盘录入 *3.将数据发给服务器端 *4.获取服务器端返回数据,打印到控制台 *5,关闭资源 * */public class TransClient {    public static void main(String[] args) {        try {            Socket s=new Socket(InetAddress.getLocalHost(), 10005);            //获取键盘数据            BufferedReader br=                    new BufferedReader(new InputStreamReader(System.in));            //定义目的,将数据写入Socket流发给服务器端//          BufferedWriter bwOut=new BufferedWriter(//                  new OutputStreamWriter(s.getOutputStream()));            PrintWriter out=new PrintWriter(s.getOutputStream(),true);            //定义一个Socket读取流,读取服务器端返回信息            BufferedReader brIn=new BufferedReader(                    new InputStreamReader(s.getInputStream()));            String line=null;            while((line=br.readLine())!=null){                if("over".equals(line))                    break;//              bwOut.write(line);//              bwOut.newLine();//              bwOut.flush();                out.println(line);                System.out.println("server :: "+brIn.readLine());            }        } catch (UnknownHostException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }}

注:上边两个程序有几行被注释了,那是被下边一行代码给替换了,它们都能成功

可能出现的问题,客户端和服务器端都在莫名的等待,这事因为它们都有阻塞式方法,可能的原因是这个方法没有读到结束标记,就一直在等
即bwOut.newLine();bwOut.flush();这两句代码被忽略是会出现这种情况

下面写一个上传文件的程序
服务器端

package fourth;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class TextServer {    public static void main(String[] args) {        try {            ServerSocket ss = new ServerSocket(10006);            Socket s=ss.accept();            BufferedReader brIn=new BufferedReader(new InputStreamReader(s.getInputStream()));            PrintWriter pw=new PrintWriter(new FileWriter("D:\\info.txt"));            String line=null;            while((line=brIn.readLine())!=null){                if (line.equals("over")) {                    break;                }                pw.println(line);            }            PrintWriter out=new PrintWriter(s.getOutputStream());            out.println("上传成功");            out.close();            s.close();            ss.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

客户端

package fourth;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;public class TextClient {    public static void main(String[] args) {        try {            Socket s = new  Socket(InetAddress.getLocalHost(),10006);            BufferedReader br =new BufferedReader(new FileReader("E:\\info.txt"));            PrintWriter out=new PrintWriter(s.getOutputStream(),true);            String line=null;            while((line=br.readLine())!=null){                out.println(line);            }            s.shutdownOutput();//关闭客户端输出流,相当于加入结束标记            BufferedReader brIn=new BufferedReader(new InputStreamReader(s.getInputStream()));            System.out.println(brIn.readLine());            s.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

over,主要注意s.shutdownOutput();结束标记

0 0