UDP的服务端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg)do{\
fprintf(stderr,"line%d\n",__LINE__);\
perror(msg);\
}while(0)
#define SER_PORT 1234
#define SER_IP "192.168.31.107"//虚拟机ip
int main(int argc, const char *argv[])
{
//创建报式套接字socket
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//bind ip和端口号
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success__%d__\n",__LINE__);
char buf[128]="";
ssize_t res=0;
struct sockaddr_in cin;//数据包从谁那里来
socklen_t addrlen =sizeof(cin);
while(1)
{
bzero(buf,sizeof(buf));//清空
//接收数据recvfrom
res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
//发送sendto
strcat(buf,"*-*");
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin))<0)
{
ERR_MSG("sento");
return -1;
}
printf("sendto success\n");
}
//关闭套接字
close(sfd);
return 0;
}
UDP的客户端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg)do{\
fprintf(stderr,"lin%d\n",__LINE__);\
perror(msg);\
}while(0)
#define SER_PORT 1234
#define SER_IP "192.168.31.107"
int main(int argc, const char *argv[])
{
//创建套接字
int cfd=socket(AF_INET,SOCK_DGRAM,0);
if(cfd<0)
{
ERR_MSG("socket");
return -1;
}
//bind,非必要绑定
//填充服务器的地址信息结构体,给下面的sendto函数使用
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);
char buf[128]="";
ssize_t res=0;
struct sockaddr_in cin;//存储数据包到哪里去
socklen_t addrlen=sizeof(cin);
while(1)
{
bzero(buf,sizeof(buf));
//发送数据sendto
printf("请输入");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
//sendto将数据发送到服务器,所以需要填充服务器的地址信息结构体
if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");
bzero(buf,sizeof(buf));
res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("%s\n",buf);
}
//关闭套接字
close(cfd);
return 0;
}
FTTP的下载
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg)do{\
fprintf(stderr,"line:%d\n",__LINE__);\
perror(msg);\
}while(0)
#define SER_PORT 69
#define SER_IP "192.168.31.195"
int download_cli(char filename[])
{
//创建报式套接字
int cfd= socket(AF_INET,SOCK_DGRAM,0);
if(cfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("socket suceess=%d__%d__\n",cfd,__LINE__);
/*//填充服务器的地址信息结构体,绑定到套接字上 给下面的sendto使用*/
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);//tftp服务器所在的ip
socklen_t addrlen=sizeof(sin);
//发送下载请求协议
char buf[516]={0};
short* p1=(short *)buf;
*p1=htons(1);//操作码
char* p2=buf+2;
strcpy(p2,filename);//要下载的文件名
char* p3=p2+strlen(p2);
*p3=0;
char* p4=p3+1;
strcpy(p4,"octet");//模式
char* p5=strlen(p4)+p4;
*p5=0;
int size=4+strlen(p2)+strlen(p4);
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG ("send");
return -1;
}
printf("发送成功\n");
//打开文件
int fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);//只写
if(fd<0)
{
ERR_MSG("open");
return -1;
}
char buf2[128]="";
ssize_t res;
while(1){
//接受服务器发送的数据包、
//提取数据包中的数据(buf+4),另存到文件里
//给服务器回复ack,组ACK包,快编号与接收到的数据包的快编号一致
//如果收到回复的是错误包,则打印错误码+错误信息,退出
bzero(buf,sizeof(buf));
res =recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("len:%ld\n",res);
//判断操作码是否是ERR
if(buf[1]==0x03)
{
printf("正在写入文件\n");
//写入文件
char *p=buf+4;
write(fd,p,res-4);
/* {*/
/*ERR_MSG("write");*/
/*return -1;*/
/*}*/
}
//发送应答包
int size=sprintf(buf2,"%c%c%c%c",0x00,0x04,buf[2],buf[3]);
printf("端口号 %d\n",sin.sin_port);
if(sendto(cfd,buf2,size,0,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("snedto");
return -1;
}
if(res-4<512)
{
printf("下载成功\n");
return 0;
}
printf("[%s :%d]:%s\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),buf);
}
//关闭套接字
close(cfd);
close(fd);
}
int uploading_cli(char filename[])//上传
{
//创建报式套接字
int cfd= socket(AF_INET,SOCK_DGRAM,0);
if(cfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("socket suceess=%d__%d__\n",cfd,__LINE__);
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);//tftp服务器所在的ip
//向这服务器发送上传请求
char buf[516] = "";
memset(buf,0,sizeof(buf));
int size = sprintf(buf,"%c%c%s%c%s%c",0x00,0x02,filename,0,"octet",0);
if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin)) < 0){
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");
struct sockaddr_in ser_sin;//ser_sin表示服务器回复时的IP和随机端口
socklen_t addrlen = sizeof(ser_sin);
ssize_t res = 0;
int size_ACK = 0;
int fd = open(filename,O_RDONLY,0666);
char r_buf[512] = "";
int read_res = 0;
char buf_ACK[4] = "";
while(1){
//接受服务器回复的ACK包
memset(buf_ACK,0,sizeof(buf_ACK));
memset(buf,0,sizeof(buf));
res = recvfrom(cfd,buf_ACK,sizeof(buf_ACK),0,(struct sockaddr *)&ser_sin,&addrlen);
if(res < 0){
ERR_MSG("recvfrom");
return -1;
}
printf("[%s:%d]\n",inet_ntoa(ser_sin.sin_addr),ntohs(ser_sin.sin_port));
printf("%d%d%d%d\n",buf_ACK[0],buf_ACK[1],buf_ACK[2],buf_ACK[3]);
//根据服务器回复的ACK包封装数据包
buf_ACK[1] = 0x03;
buf_ACK[3] = buf_ACK[3]+1;
buf[0] = buf_ACK[0];
buf[1] = buf_ACK[1];
buf[2] = buf_ACK[2];
buf[3] = buf_ACK[3];
char *p = buf+4;
read_res = read(fd,r_buf,sizeof(r_buf));
strcat(p,r_buf);
printf("buf =%ld\n",sizeof(buf));
if(sendto(cfd,buf,read_res+4,0,(struct sockaddr *)&ser_sin,sizeof(ser_sin)) < 0){
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");
if(read_res < 512){
break;
}
}
//关闭套接字
close(cfd);
}
int main (int argc, const char *argv[])
{
printf("--------请输入你要执行的操作-------\n");
printf("---------1下载--------------\n");
printf("----------2上传--------------\n");
int flag=0;
char filename[20]={0};
scanf("%d",&flag);
if(flag!=1&&flag!=2)
{
printf("请重新输入\n");
return -1;
}else if(flag==1)//下载
{
printf("请输入你要下载的文件\n");
scanf("%s",filename);
download_cli(filename); //封装下载函数
}else if(flag==2)//上传
{
printf("请输入你要上传的文件\n");
scanf("%s",filename);
uploading_cli(filename); //封装上传函数
}
return 0;
}