Socket编程

网络编程

网络编程也叫socket编程,套接字编程,网络编程。
Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

    Socket原理机制:
        通信的两端都有Socket。
        网络通信其实就是Socket间的通信。
        数据在两个Socket间通过IO传输。

网络编程三要素

    网络编程三要素:
    ip:
        一个计算的标示(找到这个计算机)
    端口:
        应用程序都会对应一个端口,用来进行通信,有效端口:0~65535,其中0~1024系统使用或保留端口(360查看端口)。
    协议:
        总共有2种协议(TCP,UDP)

1. 特殊的IP地址:

    127.0.0.1   本地回环地址,用来做一些本地测试;   
    ping IP地址: 用来检测本机是否可以和指定的IP地址的计算机可以进行正常通讯;
    ipconfig用来查看IP地址;
    xxx.xxx.xxx.255 广播地址。

2. 端口号

    物理端口:物理设备对应的端口,网卡口
    逻辑端口:用来标示我们的计算机上的进程,端口号的有效范围应该是 0-65535,其中0-1024被系统占用或者保留

3. 协议

    UDP
        把数据打成一个数据包 , 不需要建立连接
        数据包的大小有限制不能超过64k
        因为无连接,所以属于不可靠协议(可能丢失数据)
        因为无连接 ,所以效率高    
    TCP
        需要建立连接,形成连接通道
        数据可以使用连接通道直接进行传输,无大小限制
        因为有链接,所以属于可靠协议
        因为有链接,所以效率低

InetAddress:IP地址的描述类

    为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用此类表示互联网协议 (IP) 地址。 
package com.wy.inet;

import java.net.InetAddress;

public class InetTest {
    public static void main(String[] args) throws Exception {
        //ip地址可以设置为自己的ip地址测试一下
        InetAddress address = InetAddress.getByName("192.168.20.11");
        //获取主机地址
        String ha = address.getHostAddress();
        //获取主机名
        String name = address.getHostName();
        System.out.println(ha);
        System.out.println(name);   
    }
}

UDP编程

UDP协议的特点:

    1.把数据打包
    2.不需要建立连接,也称为面向无连接协议
    3.数据需打包,数据大小有限制64k
    4.无需建立连接,所以不可靠
    5.速度快

UDP通信的步骤:

    发送端步骤,UDP发送数据的步骤:
     A:创建UDP发送数据端Socket对象
     B:创建数据包,并给出数据,把数据打包
     C:通过Socket对象发送数据包 
     D:释放资源

接收端步骤:
UDP协议接收数据步骤:
     A:创建UDP接收数据端Socket对象
     B:创建一个接收数据的数据包
     C:接收数据,数据在数据包中
     D:解析数据包,并把数据显示在控制台
     E:释放资源

发送段代码:

package com.wy.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpClient {
    public static void main(String[] args) throws Exception {
        //建立发送Socket
        DatagramSocket ds = new DatagramSocket();
        byte[] buf = "I love xcc".getBytes();
        int len = buf.length;
        InetAddress address = InetAddress.getByName("192.168.20.11");
        int port = 9999;
        //发送数据包的参数为发送数据,发送数据长度,发送地址(InetAddress类型),端口号
        DatagramPacket dp = new DatagramPacket(buf, len, address, port);
        ds.send(dp);
        ds.close();

    }
}

服务端代码:

package com.wy.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServer {
    public static void main(String[] args) throws Exception {
        //接收端Socket
        DatagramSocket ds = new DatagramSocket(9999);
        //使用一个字节数组接收
        byte[] buf = new byte[1024];
        int length = buf.length;
        //创建接收端数据包,用于存放接收到的数据
        DatagramPacket dp = new DatagramPacket(buf, length);
        //进行接收
        ds.receive(dp);
        //将接受到的数据打印到控制台
        System.out.println(new String(buf,0,length));

    }
}

运行的时候,先运行客户端,再运行服务端;

使用UDP协议实现一个聊天功能:
客户端代码如下:

package com.wy.udpmultthread;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;

public class UdpClient implements Runnable{
    DatagramSocket ds;
    public UdpClient(DatagramSocket ds){
        this.ds = ds;
    }

    @Override
    public void run() {
        //键盘录入数据
        Scanner sc = new Scanner(System.in);
        try {
            InetAddress address = InetAddress.getByName("192.168.20.11");
            //指定一个端口,只要大于1024,小于65535,即可
            int port = 20000;
            String line;
            while((line = sc.nextLine())!= null){
                int len = line.getBytes().length;
                //建立发送端数据包
                DatagramPacket dp = new DatagramPacket(line.getBytes(),len,address,port);
                //发送数据
                ds.send(dp);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

服务端代码如下:

package com.wy.udpmultthread;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServer implements Runnable{
    DatagramSocket ds;
    //使用构造函数,是为了使两个线程使用同一个DatagramSocket
    public UdpServer(DatagramSocket ds){
        this.ds = ds;
    }
    @Override
    public void run() {
        try {
            byte[] buf = new byte[1024];
            int len = buf.length;
            DatagramPacket dp = new DatagramPacket(buf, len);
            ds.receive(dp);
            System.out.println(new String(buf,0,len));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

测试:

package com.wy.udpmultthread;

import java.net.DatagramSocket;

public class MultiTreadTest {
    public static void main(String[] args) throws Exception {
        DatagramSocket sk = new DatagramSocket();
        new Thread(new UdpClient(sk)).start();
        new Thread(new UdpServer(sk)).start();
    }
}

如果将ip改为192.168.20.255,则是广播地址,可以实现群聊。

TCP编程

TCP特点:

  1.需要建立通道
  2.传送大量数据无限制
  3.面向连接
  4.可靠
  5.速度慢

TCP协议通信步骤:

发送端:

TCP协议发送数据步骤:
A:创建TCP协议发送端Socket对象,指定服务器IP及端口
B:获取输出流,并写数据
C:释放资源

TCP协议是不能直接运行客户端的,必须先运行服务器。因为他是一种可靠的协议。
接收端:

TCP协议接收数据步骤:
A:创建TCP协议接收端Socket对象
B:监听客户端连接
C:获取输入流,并读取数据,显示在控制台
D:释放资源

客户端给服务端发送数据
客户端:

package com.wy.tcp;

import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        //发送端Socket
        Socket sk = new Socket("192.168.20.11", 10000);
        //键盘录入数据
        Scanner sc = new Scanner(System.in);
        String line ;
        while(true){
            line= sc.nextLine();
            //将数据写入到Socket的输出流中
            OutputStream os = sk.getOutputStream();
            os.write(line.getBytes());
        }       
    }
}

服务端代码:

package com.wy.tcp;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws Exception {
        //接收端Socket对象
        ServerSocket ss = new ServerSocket(10000);
        //监听客户端的连接
        Socket sk = ss.accept();
        while (true) {
            //接收端输入流获取数据
            InputStream is = sk.getInputStream();
            byte[] buf = new byte[1024];
            int len = is.read(buf);
            //将获取到的数据在控制台输出
            System.out.println(new String(buf, 0, len));
        }

    }
}

必须首先运行服务端,服务端进行监听,当监听到客户端的连接,则服务端开始读取数据。

下面是服务端将客户端发送来的数据写入文件:

package com.wy.tcpfile;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(20000);
        Socket sk = ss.accept();
        OutputStream os = new FileOutputStream("a.txt");
        while(true){
            InputStream is = sk.getInputStream();
            byte[] buf = new byte[1024];
            int len = is.read(buf);
            os.write(buf,0,len);
            os.flush();
        }
    }
}

使用TCP协议完成文件上传功能:

其中客户端先读取文件,然后将数据写入到输出流中;
服务端开辟一个线程,用来接收数据,并将数据写入到一个文件中;
启动服务;
客户端代码:

package com.wy.tcpfileupload;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        Socket sk = new Socket("192.168.20.5", 2000);
        BufferedReader br = new BufferedReader(new FileReader("upload.txt"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                sk.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        bw.close();
        sk.close();

    }

}

服务端代码:

package com.wy.tcpfileupload;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.UUID;

public class TcpServerThread implements Runnable {
    Socket sk;

    public TcpServerThread(Socket sk) {
        this.sk = sk;
    }

    @Override
    public void run() {

        String line;
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    sk.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new FileWriter(UUIDTest.getFileName()));
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {

        }

    }

}

UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。这里使用UUID生成上传的文件的唯一id,进行保存。这样,即使上传的是同一个文件名,也会保存下来。

package com.wy.tcpfileupload;

import java.util.UUID;

public class UUIDTest {
    public static String getFileName(){
        String fileName = UUID.randomUUID().toString();
        fileName = fileName.replaceAll("-", "")+".txt";
        return fileName;
    }
}

测试:

package com.wy.tcpfileupload;

import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(9999);
        Socket sk = ss.accept();
        new Thread(new TcpServerThread(sk)).start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值