一个作业,请大侠们提供思路,答疑解惑(100分)

  • 主题发起人 主题发起人 caomo
  • 开始时间 开始时间
C

caomo

Unregistered / Unconfirmed
GUEST, unregistred user!
: 网络室验作业:
: 1。在UDP上层实现一个可靠的协议(50%)
: 功能要求:
: (1)扩充公共函数库,包括创建Socket,bind,close,send,write
: 处理按顺序接收数据,帧损坏,丢失帧的情况
: (2)处理Ack/Check sum
: (3)一个server对多个client,以客户/服务器方式,应用所做的基本函数调用
: 例:客户端参数:hostname,prot,数据包数量,数据包大小
: server: Echo

我看了 VC的例子SIMPLEC/SIMPLES/IOCTRL,也看了一些socket编程的书籍,大部分还是
讲如何收发数据,而且 TCP和UDP都采用了尽可能相同的函数,只是服务器方有些不同。
所谓流量控制和顺序控制都是协议内部完成了。那些send/recv/sendto/recvfrom都是对
传输的数据收发,如何得到UDP包、TCP包的头部字段呢?从容关闭在UDP中如何实现?
发送什么数据?

: 应用实例要调用函数库,公共函数对高层隐藏实现细节:序号->不显示应用使用
: time
: 任选一:
: a.超时重发
: b.分段
: c.滑动窗口
: d.测试(在socket以下,模拟数据出错):丢失,损坏等
: 提交:1)。设计思想及算法
: 2)。源代码/注释->可编译执行(vc5.0/vc6.0)
: 3)。程序的执行结果
: 4)。测试用例

如何控制包的发送?如何知道丢失、损坏数据包的信息?我只知道winsock的各种函数调?
用的错误返回信息。如何控制滑动窗口?

: 2。TCP性能测试(30%)
: 要求:(选)缓冲区对象与TCP性能关系
: 测试:在同一台pc(client/server)
: 在同一Lan,不同pc上(client/server)
: 参数输出:Buffersize(rB) 缺省对象,向上,向下
: Average(Mbps) 平均速率
: Standard,Deviation(Mbps) 标准差
: 提交:1)文档 a.软/硬件环境描述
: b.测试用例及运行结果
: c.结论说明
: 2)源程序及注释,可编译执行
如何设置TCP的缓冲区大小?所谓测试是看一定时间内你发送接受的数据的总大小吗?
winsock有没有自带的测试速度的函数?没有的话就是要不停发送接受一段时间,再根据
总数量作数学运算,是吗?

小弟初学,请不吝赐教!
 
有深度,关注。
 
下面是一个例子,用底层Socket函数实现了ICMP协议的功能,改成UDP应该不难.
它实现了报文的校验和计算等底层功能.
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define IP_RECORD_ROUTE 0x7

typedef struct _iphdr
{
unsigned int h_len:4;
// Length of the header
unsigned int version:4;
// Version of IP
unsigned char tos;
// Type of service
unsigned short total_len;
// Total length of the packet
unsigned short ident;
// Unique identifier
unsigned short frag_and_flags;
// Flags
unsigned char ttl;
// Time to live
unsigned char proto;
// Protocol (TCP, UDP etc)
unsigned short checksum;
// IP checksum
unsigned int sourceIP;
unsigned int destIP;
} IpHeader;
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 // Minimum 8-byte ICMP packet (header)

typedef struct _icmphdr
{
BYTE i_type;
BYTE i_code;
// Type sub code
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
ULONG timestamp;
} IcmpHeader;

typedef struct _ipoptionhdr
{
unsigned char code;
// Option type
unsigned char len;
// Length of option hdr
unsigned char ptr;
// Offset into options
unsigned long addr[9];
// List of IP addrs
} IpOptionHeader;
#define DEF_PACKET_SIZE 32 // Default packet size
#define MAX_PACKET 1024 // Max ICMP packet size
#define MAX_IP_HDR_SIZE 60 // Max IP header size w/options
BOOL bRecordRoute;
int datasize;
char *lpdest;
void usage(char *progname)
{
printf("usage: ping -r <host> [data size]/n");
printf(" -r record route/n");
printf(" host remote machine to ping/n");
printf(" datasize can be up to 1KB/n");
ExitProcess(-1);
}

void FillICMPData(char *icmp_data, int datasize)
{
IcmpHeader *icmp_hdr = NULL;
char *datapart = NULL;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->i_type = ICMP_ECHO;
// Request an ICMP echo
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum = 0;
icmp_hdr->i_seq = 0;
datapart = icmp_data + sizeof(IcmpHeader);
memset(datapart,'E', datasize - sizeof(IcmpHeader));
}
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum &amp;
0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}

void DecodeIPOptions(char *buf, int bytes)
{
IpOptionHeader *ipopt = NULL;
IN_ADDR inaddr;
int i;
HOSTENT *host = NULL;
ipopt = (IpOptionHeader *)(buf + 20);
printf("RR: ");
for(i = 0;
i < (ipopt->ptr / 4) - 1;
i++)
{
inaddr.S_un.S_addr = ipopt->addr;
if (i != 0)
printf(" ");
host = gethostbyaddr((char *)&amp;inaddr.S_un.S_addr,
sizeof(inaddr.S_un.S_addr), AF_INET);
if (host)
printf("(%-15s) %s/n", inet_ntoa(inaddr), host->h_name);
else
printf("(%-15s)/n", inet_ntoa(inaddr));
}
return;
}

void DecodeICMPHeader(char *buf, int bytes,
struct sockaddr_in *from)
{
IpHeader *iphdr = NULL;
IcmpHeader *icmphdr = NULL;
unsigned short iphdrlen;
DWORD tick;
static int icmpcount = 0;
iphdr = (IpHeader *)buf;
// Number of 32-bit words * 4 = bytes
iphdrlen = iphdr->h_len * 4;
tick = GetTickCount();
if ((iphdrlen == MAX_IP_HDR_SIZE) &amp;&amp;
(!icmpcount))
DecodeIPOptions(buf, bytes);
if (bytes < iphdrlen + ICMP_MIN)
{
printf("Too few bytes from %s/n",
inet_ntoa(from->sin_addr));
}
icmphdr = (IcmpHeader*)(buf + iphdrlen);
if (icmphdr->i_type != ICMP_ECHOREPLY)
{
printf("nonecho type %d recvd/n", icmphdr->i_type);
return;
}
// Make sure this is an ICMP reply to something we sent!
//
if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
{
printf("someone else
's packet!/n");
return ;
}
printf("%d bytes from %s:", bytes, inet_ntoa(from->sin_addr));
printf(" icmp_seq = %d. ", icmphdr->i_seq);
printf(" time: %d ms", tick - icmphdr->timestamp);
printf("/n");
icmpcount++;
return;
}
void ValidateArgs(int argc, char **argv)
{
int i;
bRecordRoute = FALSE;
lpdest = NULL;
datasize = DEF_PACKET_SIZE;
for(i = 1;
i < argc;
i++)
{
if ((argv[0] == '-') || (argv[0] == '/'))
{
switch (tolower(argv[1]))
{
case 'r': // Record route option
bRecordRoute = TRUE;
break;
default:
usage(argv[0]);
break;
}
}
else
if (isdigit(argv[0]))
datasize = atoi(argv);
else
lpdest = argv;
}
}
//
// Function: main
//

int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET sockRaw = INVALID_SOCKET;
struct sockaddr_in dest,
from;
int bread,
fromlen = sizeof(from),
timeout = 1000,
ret;
char *icmp_data = NULL,
*recvbuf = NULL;
unsigned int addr = 0;
USHORT seq_no = 0;
struct hostent *hp = NULL;
IpOptionHeader ipopt;

if (WSAStartup(MAKEWORD(2, 2), &amp;wsaData) != 0)
{
printf("WSAStartup() failed: %d/n", GetLastError());
return -1;
}
ValidateArgs(argc, argv);

sockRaw = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
WSA_FLAG_OVERLAPPED);
if (sockRaw == INVALID_SOCKET)
{
printf("WSASocket() failed: %d/n", WSAGetLastError());
return -1;
}
if (bRecordRoute)
{
// Setup the IP option header to go out on every ICMP packet
//
ZeroMemory(&amp;ipopt, sizeof(ipopt));
ipopt.code = IP_RECORD_ROUTE;
// Record route option
ipopt.ptr = 4;
// Point to the first addr offset
ipopt.len = 39;
// Length of option header
ret = setsockopt(sockRaw, IPPROTO_IP, IP_OPTIONS,
(char *)&amp;ipopt, sizeof(ipopt));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(IP_OPTIONS) failed: %d/n",
WSAGetLastError());
}
}
// Set the send/recv timeout values
//
bread = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO,
(char*)&amp;timeout, sizeof(timeout));
if(bread == SOCKET_ERROR)
{
printf("setsockopt(SO_RCVTIMEO) failed: %d/n",
WSAGetLastError());
return -1;
}
timeout = 1000;
bread = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO,
(char*)&amp;timeout, sizeof(timeout));
if (bread == SOCKET_ERROR)
{
printf("setsockopt(SO_SNDTIMEO) failed: %d/n",
WSAGetLastError());
return -1;
}
memset(&amp;dest, 0, sizeof(dest));
//
// Resolve the endpoint's name if necessary
//
dest.sin_family = AF_INET;
if ((dest.sin_addr.s_addr = inet_addr(lpdest)) == INADDR_NONE)
{
if ((hp = gethostbyname(lpdest)) != NULL)
{
memcpy(&amp;(dest.sin_addr), hp->h_addr, hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s/n", inet_ntoa(dest.sin_addr));
}
else
{
printf("gethostbyname() failed: %d/n",
WSAGetLastError());
return -1;
}
}
//
// Create the ICMP packet
//
datasize += sizeof(IcmpHeader);
icmp_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
MAX_PACKET);
recvbuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
MAX_PACKET);
if (!icmp_data)
{
printf("HeapAlloc() failed: %d/n", GetLastError());
return -1;
}
memset(icmp_data,0,MAX_PACKET);
FillICMPData(icmp_data,datasize);
//
// Start sending/receiving ICMP packets
//
while(1)
{
static int nCount = 0;
int bwrote;
if (nCount++ == 4)
break;
((IcmpHeader*)icmp_data)->i_cksum = 0;
((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
((IcmpHeader*)icmp_data)->i_seq = seq_no++;
((IcmpHeader*)icmp_data)->i_cksum =
checksum((USHORT*)icmp_data, datasize);
bwrote = sendto(sockRaw, icmp_data, datasize, 0,
(struct sockaddr*)&amp;dest, sizeof(dest));
if (bwrote == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
printf("timed out/n");
continue;
}
printf("sendto() failed: %d/n", WSAGetLastError());
return -1;
}
if (bwrote < datasize)
{
printf("Wrote %d bytes/n", bwrote);
}
bread = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0,
(struct sockaddr*)&amp;from, &amp;fromlen);
if (bread == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
printf("timed out/n");
continue;
}
printf("recvfrom() failed: %d/n", WSAGetLastError());
return -1;
}
DecodeICMPHeader(recvbuf, bread, &amp;from);
Sleep(1000);
}
// Cleanup
//
if (sockRaw != INVALID_SOCKET)
closesocket(sockRaw);
HeapFree(GetProcessHeap(), 0, recvbuf);
HeapFree(GetProcessHeap(), 0, icmp_data);
WSACleanup();
return 0;
}
 
有难度.....
 
接受答案了.
 
后退
顶部