计算机网络实验一

本文详细介绍了计算机网络实验中TCP和UDP协议的使用。在TCP实验中,发送了一个大文件,通过TCP连接分多次发送。而在UDP实验中,发送了小文件和大文件,展示了UDP的一次性发送和分包发送。实验揭示了TCP和UDP在可靠性、流量控制上的差异,并记录了解决编程中遇到的问题和方法。
  1. 网线制作

原始线序:(顺序记忆方法:红绿蓝棕

白橙

白绿

绿

白蓝

白棕

1

2

3

4

5

6

7

8

568B:原始线序第4个与第6个交换

白橙

白绿

白蓝

绿

白棕

1

2

3

4

5

6

7

8

568A:568B线序第1个与第3个交换,第2个与第6个交换

白绿

绿

白橙

白蓝

白棕

1

2

3

4

5

6

7

8

注意事项:水晶头的塑料卡一面向下,从左到右依次按1-8的顺序排列线。

     2.网络编程

  1. TCP协议

客户-服务器模式

Client

Server

 

=socket()

socketid=socket()

 

=connect()

=bind()

分配资源

 

=listen(socketid,queuelen)

 

 

=accept()

同意建立连接,发送ack,反向连接请求,返回newsocket,建立新的套接字数据结构

三次握手

=send()

=recv()

 

=recv()

=send()

 

=close()

=close(socketid)

四次挥手

 

=close(newsocket)

 

  1. Client通过connect函数写入Server的IP地址和端口号
  2. Server的accept函数返回Client的IP地址和端口号(指针)
  3. Server通过bind函数绑定自己的IP地址和端口,周知端口号
  4. Client不需要bind函数,因为操作系统临时分片端口;也可以绑定,此时操作系统不分配
  5. Server可以向Client主动发送数据,因为三次握手后Server获得了Client的地址
  1. UDP协议

Client

Server

 

=socket()

socketid=socket()

 

 

=bind()

分配资源

=sendto()

=recvfrom()

 

=recvfrom()

=sendto()

 

=close()

=close(socketid)

 

  1. Client的sendto指明Server的IP地址和端口号
  2. Server的recvfrom指明Client的IP地址和端口号(指针)
  3. Server不可以主动向Client发送数据,因为必须接收一次才可以获得Client的地址

思考问题:为什么不在数据链路层和网络层解决可靠性问题?

1交换机和路由器要进行 流量控制、差错控制、拥塞控制,会更复杂

2不仅要在端节点解决可靠性,还要在网络中解决可靠性,网络会复杂

实验方法及具体步骤

TCP协议发送一个大文件姚静.avi

服务器端截图:

可以看到打印出了文件的长度为3838464(字节),我们使用的TCP包的大小是512(字节),所以发送次数=3838464/512=7497次;

TCP服务器端代码:

#define packet_size 512//包长度512
char *sendData = (char*)malloc(length);
char *dataptr = sendData;
ret = sendto(newSocket, dataptr, packet_size, 0, (sockaddr *)&clientAddr, iLen);//发送第一个包
int i = 1;
int send_no = (length / packet_size);//控制发送次数
while ( i < send_no)
{
		dataptr += packet_size;//指针移动512
		Sleep(5);
		if (ret == SOCKET_ERROR || ret == 0)
		{
			cout << ret << endl;
			cout << "wrong" << endl;
			return;
		}
		cout << i << "send successful!" << endl;
		if (i < length / packet_size) {
			ret = sendto(newSocket, dataptr, packet_size, 0, (sockaddr *)&clientAddr, iLen);//发送前面部分的数据
		}
		else {
			cout << "最后一段数据" << (length % packet_size) << endl;
			ret = sendto(newSocket, dataptr, length%packet_size,0,(sockaddr*)&clientAddr, iLen);//发送最后一段数据,这一段数据是文件长度%包长度
		}
		i++;
}

客户端截图:

 

UDP协议传送一个小文件zhuqi.txt

服务器端截屏:

可以看到打印出了文件长度为57,只需要发送一次就行了。

客户端截图:

UDP协议传送一个大文件姚静.avi

服务器端截图:

可以看到文件长度为3838464(字节),本次使用的UDP包的大小为53000(字节),所以发送次数=3838464/53000+1=73

部分代码解释:

#define packet_size 53000
char *sendData = (char*)malloc(length);//发送数据的字符数组
char *dataptr = sendData;//新建一个指针指向字符数组的头
ret = sendto(sSocket, dataptr, packet_size, 0, (sockaddr *)&cliadd, ilen);//发送第一个包
int i = 1;
int send_no = (length / packet_size);//发送次数=文件长度/包长度
while (i==send_no||i<send_no)
{					
	dataptr += packet_size;//字符数组指针后移53000,这样子可以做到下次从53000字节后面开始发送
	Sleep(50);
	if (ret == SOCKET_ERROR || ret == 0)
	{
		cout << ret << endl;
		cout << "wrong" << endl;
		return ;
	}
	cout <<i<< "send successful!" << endl;
	if (i < length/packet_size) {
		ret = sendto(sSocket, dataptr, packet_size, 0, (sockaddr *)&cliadd, ilen);//如果发的数据不是最后一段
	}
	else {
		cout << "最后一段数据" << (length % packet_size) << endl;
		ret = sendto(sSocket, dataptr,length%packet_size , 0, (sockaddr *)&cliadd, ilen);
//发送最后一段。单独写是因为最后一段有可能不满53000,需要发送的长度是文件长度%包长度
	}
	i++;
}

遇到的问题:

  1. UDP的sendto函数有最大长度的限制,我发现这个大小接近53000,如果超过了,sendto函数会返回-1。

解决方法:分包发送

(2)TCP的recv函数可以接收两个send,甚至多个,他们之间不是像udp那样一一对应的,导致代码从udp移植到tcp的时候出现了问题。

解决方法:搜索到tcp也可以使用recvfrom和sendto函数,并且我让所有的sendto都发送同样的大小的包。

 

参考文献

UDP传输数据及文件

https://blog.csdn.net/ni9htmar3/article/details/53556279

Linux下Socket网络编程send和recv使用注意事项

https://blog.csdn.net/K346K346/article/details/48735595

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值