目录
实验目的及要求:
一、实验原理:
二、操作步骤:
三、实验数据
1、模拟火车站4个窗口同时卖50张票
2、使用UDP协议实现用户信息的发送和接收功能
3、运用TCP协议实现向服务器上传文件。
实验结果及分析:
个人简介
- 作者简介:大家好!我是yukki。
- 个人主页:yukki.
- ?喜欢:🌈点赞🌈收藏🌈一键三连!
- 共勉
实验目的及要求:
实验目的:通过该实验使学生了解网络通信协议;实现多线程的同步问题;掌握IP地址和端口号的作用;掌握UDP和TCP通信的实现。
实验要求:
1. ?分别是由同步代码段、同步方法和同步锁的方法实现线程同步(模拟火车站4个窗口同时卖50张票);
2.?使用UDP协议实现用户信息的发送和接收功能;
3.??运用TCP协议实现向服务器上传文件。
一、实验原理:
TCP协议能够检测和恢复IP层提供的主机到主机的通信中可能发生的保温丢失、重复以及其他错误。TCP提供了一个可信赖的字节流通道,这样应用程序就不需要考虑这些问题。同时,TCP协议是一种面向链接的协议,在使用TCP进行通信之前,两个应用程序之间需要建立一个TCP连接,而这个连接又涉及到两台电脑需要完成握手消息的交换。
UDP协议不会对IP层产生的错误进行修复,而是简单的扩展了IP协议“尽力而为”的数据报文服务,使他能狗在应用程序之间工作,而不是在主机之间工作,因此使用UDP协议必须要考虑到报文丢失,顺序混乱问题。
IP地址是连接在因特网上的主机的标识符。
端口(Port)是一个虚拟的、逻辑上的概念。可以将端口理解为一道门,数据通过这道门流入流出,每道门有不同的编号,就是端口号。
多线程,是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作“线程”,利用它编程的概念就叫作“多线程处理” 。
二、操作步骤:
1、模拟火车站4个窗口同时卖50张票
(1)窗口买票代码
(2)结果截图
2、使用UDP协议实现用户信息的发送和接收功能
(1)chatroom聊天室、发送端、接收端
(2)chatroom聊天室、发送端、接收端
? (3)? ?实验截图
3、运用TCP协议实现向服务器上传文件。
(1)客户端代码
(2)服务器端代码
(3)结果截图
三、实验数据
1、模拟火车站4个窗口同时卖50张票
(1)窗口买票代码
package helloworld;
public class a {
public static void main(String[] args) {
Teacher t = new Teacher();
new Thread(t, "窗口1").start();
new Thread(t, "窗口2").start();
new Thread(t, "窗口3").start();
new Thread(t, "窗口4").start();
}
}
?
class Teacher implements Runnable {
private int num = 50;
public void run() {
while (true) {
piao();
if (num <= 0) {
break;
}
}
}
private synchronized void piao() {
if (num > 0) {
try {
Thread.sleep(1000); // 经过的线程休眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 卖出的票" + num--);
}
}
}
2、实验截图
2、使用UDP协议实现用户信息的发送和接收功能
(1)chatroom聊天室、发送端、接收端
package tcp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/**
* @author zzc
* @create 2022-05-04 14:31
*/
public class chatroom {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("请输入我的端口号");
int myport = sc.nextInt();
System.out.println("请输入对方的端口号");
int targetport = sc.nextInt();
DatagramSocket socket = new DatagramSocket(myport);
new Thread(new send(socket, targetport)).start();
new Thread(new receiver(socket)).start();
}
}
class send implements Runnable {
DatagramSocket socket;
int port;
public send(DatagramSocket socket, int port) {
this.socket = socket;
this.port = port;
}
@Override
public void run() {
//1、创建码头
try {
// socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
String data = sc.nextLine();
DatagramPacket packet = new DatagramPacket
(data.getBytes(), data.getBytes().length, InetAddress.getByName("127.0.0.1"),port);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class receiver implements Runnable {
DatagramSocket socket;
public receiver(DatagramSocket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//1、
// DatagramSocket socket = new DatagramSocket(5555);
//2、
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
//3、
while (true) {
socket.receive(packet);
//4、
String str = new String(packet.getData(), 0, packet.getLength());
System.out.println("我收到的信息来自于IP:" + packet.getAddress() + ":pock:" + packet.getPort());
System.out.println("信息是" + str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)结果截图
3、运用TCP协议实现向服务器上传文件。
服务器端的步骤 1、获取一个连接地址和指定的端口号 2. 等待着客户端的链接 3.读取客户端的消息。输入流 4.文件输出 5.通知客户端接受完毕 6.关闭资源 客户端的步骤 1.获取服务器的地址,端口号 2.创建socket连接获取网络字节输出流 3. 读取需要上传的文件 4. 将读取的文件写出,使用字节流 5. 通知服务器,请求已经结束了 6. 通知服务器接受完毕,断开连接 7. 关闭资源
(1)客户端代码
package TCPServer;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPfileClient {
public static void main(String[] args)throws Exception {
// 1、创建socket对象,向服务器提出连接请求
Socket client = new Socket("127.0.0.1", 9999);
// 2、开启上传图片
OutputStream os = client.getOutputStream();
//
FileInputStream file = new FileInputStream("C:123.jpg");
byte[] buf = new byte[1024];
int len = 0;
while ((len = file.read(buf)) != -1) {
os.write(buf, 0, len );
}
System.out.println("图片上传结束");
client.shutdownOutput();
// 3、等待服务器回应(假如服务器接受图片后会回应:图片上传成功)
InputStream in = client.getInputStream();
len = in.read(buf);
while (len != -1) {
System.out.println(new String(buf, 0, len));
len = in.read(buf);
}
// 4、关闭资源
in.close();
os.close();
file.close();
client.close();
}
}
(2)服务器端代码
package TCPServer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPfileserver {
public static void main(String[] args)throws Exception{
// 1、创建服务器对
ServerSocket server =new ServerSocket(9999);
// 2、接受客户端请求
Socket client=server.accept();
System.out.println("接受客户端请求");
// 3、读取客户端发送的信息:
// 3.1、建立一个文件夹
File filemr=new File("D:123");
if(!filemr.exists())
{
filemr.mkdir();
}
// 3.2、给收到的图片命名(IP+编号.jpg)
String ip=client.getInetAddress().getHostAddress();
int count=1;
File file=new File(filemr,ip+"("+count+").jpg");
while(file.exists())
{
file=new File(filemr,ip+"("+(count++)+").jpg");
}
// 3.3、从客户端读入数据,写入本地图片
InputStream is=client.getInputStream();
FileOutputStream fileout=new FileOutputStream(file);
byte[] buf=new byte[1024];
int len=0;
while((len=is.read(buf))!=-1)
{
fileout.write(buf,0,len);
}
// 4、读取完数据后,向客户端回应
OutputStream os=client.getOutputStream();
os.write("图片上传成功".getBytes());
// 5、关闭和客户端的连接
is.close();
os.close();
fileout.close();
client.close();
}
}
(3)结果截图
实验结果及分析:
1、实验中出现过的问题或错误分析
(1)在聊天室的发送端是,输入信息在try语句之内,而非之外,否则在while语句循环时,发送信息只有一条,不能连续发送
(2)在聊天室中,new的线程的new的发送端和接收端传入的socket都是以接口的方式继承,在对应的接口继承私有化成为成员变量
(3)客户端以InputStream发送,OutputStream接收,服务器端与之相反。
2、保证实验成功(或程序运行正确)的关键问题
(1)窗口买票时的synchronized的原理实现建议看下面的博客
传送门
(2)?@Override的三个作用
????????1. 可以给你当作注释用,感觉这个也不能说明什么,注释也没什么用。
??? ? ? 2. 可以告诉读你代码的人,这是对它父类方法的重写,其实很多代码规范没有为什么,规范就是规范,代码的可读性还是很重要的。
????????3. 编译器可以给你验证@Override下面的方法名称是否是你父类中所有的,如果没有就会报错。
(3)先运行服务器端,在运行客户端,上传文件必须遵循tcp协议,也就是三次握手。其实也是根据三次握手编写代码
|