VC++SOCKET

VC++SOCKET,第1张

这是c的,在linux,deliya 等运行过的,我的网络作业

必须在linux里编译运行,

编译命令cc -o 要生成可执行程序的文件名 要编译的文件名

如:cc -o server server.c

运行时 ./server 参会数

./表示从当前目录搜索

我觉得socket生成的int形的连接号,相当于用open命令返回的int型的文件句柄,就把它当文件一样用服务器写,客户端读出来,再写到本地硬盘上

这里有关shoct编程的一些知识

http://hi.baidu.com/yanzi52351/blog/item/134827d6b806b12806088b21.html

/*

by:yanzi52351

本程序是client端

程序功能:

连接server端接收数据,另存为text2.txt

发送文件在参数中指定

运行参数#./client ip port sendname

ip 服务器ip地址

port 服务器连接端口

sendname 本端要向服务器端要发送的文件名

运行环境:

Linux,UNIX,Windows下的CYGWIN

*/

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#define BUFSIZE 128

#define PERM 0644 /* 创建文件的默认属性*/

#define littleBUFSIZE 126

/*#definechar DATA[]="Half a league, half a league..."*/

main(argc,argv)

int argc

char *argv[]

{

struct hostent *hp,*gethostbyname()

int outfile,infile,msgsock,sock,length,clilen,rval,realn,i=0

ssize_t nread

char buf[BUFSIZE]

char charnum

struct sockaddr_in server,client

if(argc<4)

{

printf("输入的参数不正确\n\n")

printf("运行参数#./server ip port sendname\n")

printf(" ip 服务器ip地址\n")

printf(" port 服务器连接端口\n")

printf(" sendname 本端要向服务器端要发送的文件名\n\n\n")

exit(1)

}

/***************************建立Socket连接*******************************/

sock=socket(AF_INET,SOCK_STREAM,0)/* 申请一个套节字,AF_INET,SOCK_STREAM是指TCP协议*/

if (sock<0)

{

perror("opening stream socket")

exit(1)

}

server.sin_family=AF_INET/*必然的,这里指的是Internet协议*/

hp=gethostbyname(argv[1])/*根据主机名查地址,返回指针指向hostent结构*/

if (hp==0) /*当没有此主机名时*/

{

fprintf(stderr,"%s:unknow host\n",argv[1])

exit(2)

}

memcpy((char *)&server.sin_addr,(char *)hp->h_addr,hp->h_length)/*拷贝Internet地址*/

server.sin_port=htons(atoi(argv[2]))/*argv[2]是端口号,2000-5000都可以,这里,要看server的输出了*/

if (connect(sock,(struct sockaddr *)&server,sizeof server)<0) /*根据server地址连接sock,建立一条真实的连接*/

{

perror("请检查端口是否正确")

exit(1)

}

printf("连接成功\n\n")

/*************************上面建好了Socket连接,下面就是怎么用sock了,和对待文件一样***********/

if((outfile=open("test2.txt",O_WRONLY|O_CREAT|O_TRUNC,PERM))==-1)

{

printf("创建文件出错\n")

exit(1)

}

memset(buf,0,sizeof buf)/*缓冲区清零*/

printf("*****************下面是 client 端接收文件时数据的传送记录*****************\n")

printf("***************** client 端将接收的文件另存为test2.txt *****************\n\n")

while((nread=read(sock,buf,BUFSIZE))>0)/*从sock读取传来的文件内容到缓冲区*/

{

realn=buf[BUFSIZE-2]/*查一下有效内容长度*/

if(realn==-128)

{

printf("文件test2.txt接收完了\n")

break

}

printf("从sock读了第 %3d 块数据,大小是 %3d ,",++i,nread)

realn=buf[BUFSIZE-2]/*查一下有效内容长度*/

printf("有效长度是 %3d ,编号是%c\n\n",realn,buf[BUFSIZE-1])

if(write(outfile,buf,realn)<realn) /*将缓冲区的内容写到文件里*/

printf("写文件时出了错\n")

charnum=buf[BUFSIZE-1]

memset(buf,0,sizeof buf)/*缓冲区清零*/

buf[0]=charnum/*准备告诉对方收到了第几块i+48是i的ASCII值*/

write(sock,buf,BUFSIZE)/*把收到信息发回去*/

}

close(outfile)

/**********************************下面是发送部分****************************************************************/

if((infile=open(argv[3],O_RDONLY))==-1)

{

printf("找不到文件%s或打不开,停止运行\n",argv[3])

exit(1)

}

printf("\n\n\n*****************下面是 client 端发送文件时数据的传送记录*****************\n")

printf("****************** client 端 发送的文件是%13s ****************\n\n",argv[3])

i=0/*****重置计数器*********/

memset(buf,0,sizeof buf)/*缓冲区清零*/

while((nread=read(infile,buf,littleBUFSIZE))>0) /*将文件读到缓冲区*/

{

printf("从文件中读大小为 %3d 的数据,",nread)

buf[littleBUFSIZE]=nread/*把实际大小放在发的数据的最后一位*/

i++

buf[littleBUFSIZE+1]=(i%10)+48/*i+48是i的ASCII值*/

if(write(sock,buf,littleBUFSIZE+2)<=nread)

printf("写sock出了错")

else

printf("往sock发了第 %3d 块,大小是 %3d ,",i,nread)

memset(buf,0,sizeof buf)/*缓冲区清零*/

if(rval=read(sock,buf,littleBUFSIZE+2)<0)

/*从scok读对方收到信息后的应答*/

printf("读sock出了错\n")

else

printf("对方收到块编号 %3s \n\n",buf)

}/*while*/

printf("文件%s发送完毕\n\n",argv[3])

close(infile)

close(sock)

exit(0)

}

/*

by:yanzi52351

本程序是server端

程序功能:

传输一个特定的文件,名字为test.txt

传送完后,开始接收client端发过来的文件

另存收到数据的文件名为是程序的第一个参数

在本端文件是以追加方式打开的

所以会把每次client端传过来的数据都保存起来

而不会清删除以前的

接收完文件后,会继续监听端口,等待client的连接

运行参数#./server savename

savname 存储客户端发过来数据的文件名

运行环境:

Linux,UNIX,Windows下的CYGWIN

*/

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#define TRUE 1

#define littleBUFSIZE 126

#define BUFSIZE 128

#define PERM 0644 /* 创建文件的默认属性*/

/*发的时候是128,*/

main (argc,argv)

int argc

char *argv[]

{

int sock,length,clilen

struct sockaddr_in server,client

int msgsock

struct hostent *hp,*gethostbyname()

int outfile,infile

ssize_t nread

char buf[BUFSIZE]

int rval

int realn

int i=0,j/*小计数器*/

char charnum

if(argc<2)

{

printf("参数不正确\n\n")

printf("运行参数#./server savename\n")

printf(" savname 存储客户端发过来数据的文件名\n\n\n")

exit(1)

}

/******************************建立Socket连接*********************************/

sock=socket(AF_INET,SOCK_STREAM,0)

if (sock<0)

{

perror("opening stream socket")

exit(1)

}

server.sin_family=AF_INET

server.sin_addr.s_addr=INADDR_ANY/*必然的,这里指的是Internet协议*/

server.sin_port=0/*这里,是让系统自动分配一个端口号,在1024到5000之间*/

if (bind(sock,(struct sockaddr *)&server,sizeof server)<0) /*将IP地址和端口号绑到sock上*/

{

perror("binding stream socket")

exit(1)

}

length=sizeof server

if (getsockname(sock,(struct sockaddr *)&server,&length)<0) /*获得指定socket的本地地址,成功返回0,错误返回-1*/

{

perror("getting socket name")

exit(1)

}

printf("Socket port # %d\n",ntohs(server.sin_port))/*打印出系统分的端口号,给client用*/

listen(sock,5)/*5个连接请求排队等待,一般5个*/

do{

printf("正在监听端口 %d ,等待用户连接.要停止此此服务,按CTRL+C\n",ntohs(server.sin_port))

/****************现在是等待客户来连接,如果来客户了,那就建好了socket,就可以当文件使用**********/

clilen=sizeof client

msgsock=accept(sock,(struct sockaddr *)&client,(int *)&clilen)/*创建一个新的与sock相同的socket并返回其值*/

if (msgsock==-1) /*非并发处理,反复型*/

perror("accept")

else

{ /**********这里开始进行文件处理,一直到最后************/

printf("有一个链接接入\n\n")

if((infile=open("test.txt",O_RDONLY))==-1)

{

printf("找不到文件test.txt或打不开,停止运行\n")

exit(1)

}

printf("********************下面是 server 端发送文件时数据的传输记录*****************\n")

printf("******************** server 端发送的文件是test.txt ********************\n\n")

memset(buf,0,sizeof buf)/*缓冲区清零*/

while((nread=read(infile,buf,littleBUFSIZE))>0) /*将文件读到缓冲区*/

{

printf("从文件中读大小为 %3d 的数据,",nread)

buf[littleBUFSIZE]=nread/*把实际大小放在发的数据的最后一位*/

i++

buf[littleBUFSIZE+1]=(i%10)+48/*i+48是i的ASCII值*/

if(write(msgsock,buf,littleBUFSIZE+2)<=nread)

/*将缓冲区的内容写到sock*/

printf("写sock出了错\n")

else

printf("往sock发了第 %3d 块,大小 %3d ,",i,nread)

memset(buf,0,sizeof buf)/*缓冲区清零*/

if(rval=read(msgsock,buf,littleBUFSIZE+2)<0)

/*从scok读对方收到信息后的应答*/

printf("读sock出了错\n")

else

printf("对方收到块编号 %3s \n\n",buf)

}/*while*/

memset(buf,0,sizeof buf)

buf[littleBUFSIZE]=128

write(msgsock,buf,littleBUFSIZE+2)

printf("文件test.txt发送完毕")

close(infile)

}/*else*/

/**************************************************接收文件****************************/

if((outfile=open(argv[1],O_WRONLY|O_CREAT|O_APPEND,PERM))==-1)/*如果文件不存在创建文件,如果存在以追加方式打开*/

{

printf("创建文件出错\n")

exit(1)

}

printf("\n\n\n**************下面是 server 端接收文件时数据的传输记录*************\n")

printf("************ server 端将接收的文件另存为%13s **********\n\n",argv[1])

i=0

memset(buf,0,sizeof buf)/*缓冲区清零*/

while((nread=read(msgsock,buf,BUFSIZE))>0)/*从sock读取传来的文件内容到缓冲区*/

{

printf("从sock读了第 %3d 块数据,大小是 %3d ,",++i,nread)

realn=buf[BUFSIZE-2]/*查一下有效内容长度*/

printf("有效长度是 %3d ,编号是%3c\n\n",realn,buf[BUFSIZE-1])

if(write(outfile,buf,realn)<realn) /*将缓冲区的内容写到文件里*/

printf("写文件时出了错\n")

charnum=buf[BUFSIZE-1]

memset(buf,0,sizeof buf)/*缓冲区清零*/

buf[0]=charnum/*准备告诉对方收到了第几块i+48是i的ASCII值*/

write(msgsock,buf,BUFSIZE)/*把收到信息发回去*/

}

close(outfile)

close(msgsock)

printf("文件%s接收完毕\n\n\n",argv[1])

}

while(1)

exit(0)

}

server.c是服务器端

程序功能:

运行参数#./server savename

savname 存储客户端发过来数据的文件名

传输一个特定的文件,名字为test.txt

传送完后,开始接收client端发过来的文件

另存为savname

在本端文件savname是以追加方式打开的

所以会把每次client端传过来的数据都保存起来

而不会清删除以前的

接收完文件后,会继续监听端口,等待client的连接

client.c是客户端

程序功能:

运行参数#./client ip port sendname

ip 服务器ip地址

port 服务器连接端口

sendname 本端要向服务器端要发送的文件名

连接server端接收数据,另存为text2.txt

发送文件sendname

//通过TCP实现:

#define PORT 34000

void SendFile(LPCTSTR strFilename) //参数为发送文件路径及文件名

{

AfxSocketInit(NULL)

CSocket sockSrvr

sockSrvr.Create(PORT)// Creates our server socket

sockSrvr.Listen()// Start listening for the client at PORT

CSocket sockRecv

sockSrvr.Accept(sockRecv)// Use another CSocket to accept the connection

CFile myFile

if(!myFile.Open(strFilename, CFile::modeRead | CFile::typeBinary))

return

int myFileLength = myFile.GetLength()// Going to send the correct File Size

sockRecv.Send(&myFileLength, 4)// 4 bytes long

byte* data = new byte[myFileLength]

myFile.Read(data, myFileLength)

//1024

int iRet

iRet = sockRecv.Send(data, myFileLength)//Send the whole thing now

cout <<"Ret = " <<iRet <<endl

cout <<"send file over!" <<endl

myFile.Close()

delete data

sockRecv.Close()

}

//接收文件

#define PORT 34000

void GetFile(LPCTSTR strFilename) //参数为保存文件的路径及文件名

{

AfxSocketInit(NULL)

CSocket sockClient

sockClient.Create()

sockClient.Connect("127.0.0.1", PORT)// "127.0.0.1" is the IP to your server, same port

int dataLength

sockClient.Receive(&dataLength, 4)//Now we get the File Size first

byte* data = new byte[dataLength]

sockClient.Receive(data, dataLength)//Get the whole thing

CFile destFile(strFilename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary)

destFile.Write(data, dataLength)// Write it

destFile.Close()

cout <<"Recive file over!" <<endl

delete data

sockClient.Close()

}

楼上已经把如何建立socket说明了,我只讲一下数据封装和传输过程:

1、UDP 137服务已经启动,并且会回应接受的数据包;

2、发送端的应用准备发送的数据;

3、调用socket,指明目标地址和端口(137),源地址和端口可以指定,也可以忽略;

4、socket封装UDP包,增加UDP包头,进而封装IP包,增加IP包头;

5、socket调用底层驱动(链路层),将IP包封装成物理链路上传输的帧,以以太网为例,会增加帧头,包括源MAC和目标MAC,当然中间会用到ARP,解析出IP和MAC的对应关系,由协议栈完成,应用可以不必理会;

6、底层的数据帧通过物理链路传输到对方;

7、对方接收后,反过来从底层向上层,逐渐剥去帧头、IP头、UDP头,得到实际的数据,并根据UDP头部的目标端口,传送给上层的应用,137端口服务;

8、137端口服务处理后,反后头来,发送回应数据,发送过程同上。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11970858.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存