网络编程详解

网络编程中有两个主要的问题:

(1)如何准确的定位网络上一台或多台主机(IP和端口号)

  • IP地址是唯一标识网络上的一台计算机(通信实体),网络中的www.baidu.com是域名,对应着某一个IP地址。
  • 在Java中使用InetAddress类代表IP。
  • 本地回环地址:127.0.0.1或者localhost。
  • 端口号是标识正在计算机上运行的进程(程序)
  • 不同的进程有不同的端口号,用16位的二进制表示,即0-65535之间。常见的有tomcat的8080端口,mysql的3306端口。
  • 最后,IP地址和端口号的组合,叫做网络套接字(Socket)。进程之间的通信需要借助IP地址和端口号,即网络套接字(Socket)

(2)找到主机后如何可靠高效地进行数据传输(网络通信协议)

传输层协议

(1)TCP协议(传输控制协议,Transmission Control Protocol)

  • 使用TCP协议前,须先建立TCP连接,形成数据通道
  • 传输前,采用“三次握手”方式,是可靠的
  • TCP协议进行通信的两个应用进程:客户端,服务器
  • 在连接中可进行大数据量的传输
  • 传输完毕,需释放已建立的连接,效率低

(2)UDP协议(用户数据报协议,User Datagram Protocol)

  • 将数据,源,目的封装成数据报,不需要建立连接
  • 每个数据报的大小限制在64K内
  • 因无需连接,故是不可靠的
  • 发送数据结束时,无需释放资源,速度快

基于TCP的网络编程

基于TCP的网络编程

(1)客户端Socket的工作过程包含以下四个基本的步骤:

  • 创建Socket:根据指定服务器端的IP地址或端口号构造Socket类对象。若服务器端响应,则建立客户端到服务器的通信线路;若连接失败,会出现异常。
  • 打开连接到Socket的输入/输出流:使用getInputStream()方法获得输入流,使用getOutpurStream()方法获得输出流,进行数据传输。
  • 按照一定的协议对Socket进行读/写操作:通过输入流读取服务器端返回的信息,通过输出流写入线程。
  • 关闭Socket:断开客户端到服务器的连接,释放线路。

(2)服务器端ServerSocket的工作过程包含以下四个基本的步骤:

  • 调用ServerSocket(int port):创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
  • 调用accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
  • 调用该Socket类对象的getOutputStream()和getInputStream():获取输出流和输入流,开始网络数据的发送和接收。
  • 关闭ServerSocket和Socket的对象:客户端访问结束,关闭通信套接字。

ServerSocket对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员,也就是说,服务器必须事先建立一个等待客户请求建立套接字连接的ServerSocket对象。

Socket对象是客户端通信的节点,创建的同时会自动向服务器发起连接。

源码

客户端:

package cn.csu.demo;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	public static void main(String[] args) {
		Socket socket=null;
		OutputStream os=null;
		try {
			//1.创建一个Socket对象,通过构造器指明服务器端的IP地址,以及其接收程序的端口号
			socket = new Socket(InetAddress.getByName("localhost"),9090);
			//2.getOutputStream():发送数据
			os = socket.getOutputStream();
			//3.具体的输出过程
			os.write("我是客户端,请多关照".getBytes());
		}  catch (IOException e) {
			e.printStackTrace();
		}finally{
			//4.关闭相应的流和Socket
			if(os!=null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(socket!=null){
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

服务器端:

package cn.csu.demo;

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

public class Server {
	public static void main(String[] args) {
		ServerSocket serversocket=null;
		Socket socket=null;
		InputStream is=null;
		try {
			//1.创建一个ServerSocket的对象,通过构造器指明自身的端口号
			serversocket = new ServerSocket(9090);
			//2.调用其accept()方法,返回一个Socket对象
			socket = serversocket.accept();
			//3.调用Socket对象的getInputStream()方法,获取一个从客户端发送过来的输入流
			is = socket.getInputStream();
			//4.对获取的输入流进行的操作
			byte [] b=new byte[20];
			int len;
			while((len=is.read(b))!=-1){
				String str=new String(b,0,len);
				System.out.println(str);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//关闭相应的流以及Socket,ServerSocket的对象
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(socket!=null){
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(serversocket!=null){
				try {
					serversocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

基于UDP的网络编程

  • DatagramSocketDatagramPacket实现了基于UDP协议的网络编程。
  • UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不能保证UDP数据报一定能够安全送到目的地,也不能确定是吗时候可以抵达。
  • DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号,以及接收端的IP地址和端口号。
  • UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接。

工作流程:(发送端与接收端流程一样)

  • DatagramSocket与DatagramPacket
  • 建立发送端和接收端
  • 建立数据报
  • 调用DatagramSocket的发送和接收方法
  • 关闭DatagramSocket

源码

客户端(发送端):

package cn.csu.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class Client {
	public static void main(String[] args) {
		DatagramSocket ds=null;
		try {
			ds = new DatagramSocket();
			byte [] b="你好,我是要发送的数据".getBytes();
			//创建一个数据报,每一个数据报不能大于64K,都记录着数据信息,发送端的IP,端口号,以及要发送到的接收端的IP,端口号
			DatagramPacket dp=new DatagramPacket(b, 0, b.length, InetAddress.getByName("localhost"), 9090);
			ds.send(dp);
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(ds!=null){
				ds.close();
			}
		}
	}
}

服务器端(接收端):

package cn.csu.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Server {
	public static void main(String[] args) {
		DatagramSocket ds=null;
		try {
			ds=new DatagramSocket(9090);
			byte [] container=new byte[1024];
			DatagramPacket dp=new DatagramPacket(container, 0, container.length);
			ds.receive(dp);
			String str=new String(dp.getData(),0,dp.getLength());
			System.out.println(str);
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(ds!=null){
				ds.close();
			}
		}
	}
}

基于TCP协议的多线程服务器

服务端:

package com.csu.marden;

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

public class TCPServer {
	public static void main(String[] args) throws IOException {
        //创建socket,绑定到65000端口
        ServerSocket serverSocket=new ServerSocket(65000);
        //循环用以监听
        while (true){//这是多线程的,通过循环创建多个socket来实现
            //监听65000端口,直到有客户端信息发过来
            Socket socket=serverSocket.accept();
            //执行相关操作
            new CaluteLength(socket).start();
        }
    }


}

线程类:

package com.csu.marden;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class CaluteLength extends Thread{
	//以Socket为成员变量
    private Socket socket;
    public CaluteLength(Socket socket){this.socket=socket;}

    @Override
    public void run(){
        try {
            //获取输入流
            InputStream inputStream=socket.getInputStream();
            int ch=0;
            byte[] buff=new byte[1024];
            //buff用来读取输入的内容,ch用来获取数组长度
            ch=inputStream.read(buff);
            String content=new String(buff,0,ch);//把字节流转为字符串

            System.out.println(content);

        } catch (IOException e) {
            e.printStackTrace();
        } 

    }


}

客户端1:

package com.csu.marden;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;

public class TCPClient1 {
	public static void main(String[] args) throws IOException {
       

        //转为byte数组,写到输入流中
        for(int i=0;i<100;i++){
        	 //创建Socket,并指定连接的是本机的端口号为65000的服务器socket
            Socket socket=new Socket("127.0.0.1",65000);
            // 获取输出流
            OutputStream outputStream=socket.getOutputStream();
            
            String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
   	     Random random=new Random();
   	     StringBuffer sb=new StringBuffer();
   	     for(int j=0;j<6;j++){
   	       int number=random.nextInt(62);
   	       sb.append(str.charAt(number));
   	     }
            
            
        	outputStream.write(new String("客户端1"+":"+"socket"+i+":"+sb.toString()).getBytes());
        	try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	outputStream.close();
            socket.close();
        }
        

        
    }


}

客户端2:

package com.csu.marden;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;

public class TCPClient2 {
	public static void main(String[] args) throws IOException {


        //转为byte数组,写到输入流中
        for(int i=0;i<100;i++){
        	 //创建Socket,并指定连接的是本机的端口号为65000的服务器socket
            Socket socket=new Socket("127.0.0.1",65000);
            // 获取输出流
            OutputStream outputStream=socket.getOutputStream();
            
            String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      	     Random random=new Random();
      	     StringBuffer sb=new StringBuffer();
      	     for(int j=0;j<6;j++){
      	       int number=random.nextInt(62);
      	       sb.append(str.charAt(number));
      	     }
            
            outputStream.write(new String("客户端2"+":"+"socket"+i+":"+sb.toString()).getBytes());
        	try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	outputStream.close();
            socket.close();
        }
    }

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Socket是一种进程间通信的方式,它可以用于实现网络编程。在Python中,我们可以使用TCP Socket进行网络编程。TCP是一种面向连接的传输层协议,它保证了数据的可靠传输。 在Python中,我们可以使用socket模块来创建和操作Socket。可以使用ServerSocket类的构造函数来创建Server Socket,并且可以指定端口号、连接队列大小以及绑定的IP地址。 在建立Socket连接时,如果远程主机不可访问,会出现阻塞的情况。为了避免出现长时间的阻塞,可以设置超时时间。可以使用setSoTimeout方法设置Socket的超时时间,单位为毫秒。 通过使用socket模块和TCP Socket,我们可以实现客户端和服务器之间的通信。客户端可以使用Socket连接到服务器,并发送数据。服务器可以监听指定的端口,并接受客户端的连接请求,并处理客户端发送的数据。这样就实现了基本的Socket网络编程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [详解Python Socket网络编程](https://download.csdn.net/download/weixin_38715831/13776658)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Socket网络编程详解](https://blog.csdn.net/RuiKe1400360107/article/details/86605753)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值