C语言通过网络实现发送文件的一点记录
Code First.
Server.c代码分析。
1.引入一些头文件和dll.
#include <winsock2.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #pragma comment(lib, "ws2_32.lib")
2.服务器建立Socket套接字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void main(void){ WSADATA wsaData; SOCKET MainSocket;//Socket对象 SOCKADDR_IN sin;//Socket结构 int Port = 5151;//端口 int Ret;//返回值 // 初始化,加载系统资源 if ((Ret = WSAStartup(MAKEWORD(2,2),&wsaData) != 0)) { printf("WSAStartup 失败: %d\n",Ret); return ; } //创建套接字 if ((MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) { printf("Socket 创建失败: %d\n",WSAGetLastError()); WSACleanup();//回收资源 return ; } //填充sockaddr_in结构 sin.sin_family = AF_INET; sin.sin_port = htons(Port); sin.sin_addr.s_addr = htonl(INADDR_ANY);//操作系统分配地址 //绑定地址 if (bind(MainSocket,(SOCKADDR *)&sin,sizeof(sin)) == SOCKET_ERROR) { printf("绑定失败: %d\n",WSAGetLastError()); WSACleanup(); return ; } //监听 if ( listen(MainSocket,5) == SOCKET_ERROR) { printf("监听失败: %d\n",WSAGetLastError()); return ; } printf("We are awaiting a connection on port %d.\n", Port); // 循环处理客户连接请求 while(1) { SOCKADDR_IN ClientAddr;//声明新的Socket结构体 int ClientAddrLen = sizeof(ClientAddr);//结构体长度 // 接收新的客户机,返回与客户机连接的套接字 SOCKET NewConnection = accept(MainSocket,(SOCKADDR *)&ClientAddr,&ClientAddrLen); if (NewConnection == INVALID_SOCKET) { continue;//结束当前循环,进入下一次,获取新的连接 } // 启动交互线程 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MutilThread, (void*)NewConnection, 0, NULL); } //释放资源 closesocket(MainSocket); WSACleanup(); }
3.发送文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
char FileTrans1(SOCKET sock, char *filename) { char buf[8192];//缓冲数组 FILE *fp;//文件指针 struct _stat info;//结构体描述 int filesize ;//文件大小 int res ;//发送结果 int blocks ;//文件块 int i;//循环索引 _stat(filename,&info);//获取文件大小 filesize = info.st_size; printf("文件大小: %d\n", filesize); fp = fopen(filename,"rb"); if (fp == NULL) { printf("文件打开错误..\n"); // exit(1); return -1; } //发送文件大小 res = send(sock,(char *)&filesize,sizeof(filesize),0); printf("发送大小: %d\n",res); //读文件 blocks = filesize /sizeof(buf) + 1; printf("文件 blocks : %d\n",blocks); for(i = 0; i < blocks; i++) { //清空缓冲区 memset(buf,0,sizeof(buf)); //读取一个数据块 fread(buf,sizeof(buf),1,fp); //发送一个数据块 res = send(sock,buf,sizeof(buf),0); printf("第 %d 次发送: %d\n", i+1,res); } //发送完毕,关闭文件指针 fclose(fp); return 0; }
Client.c
测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <winSock2.h> #include <stdlib.h> #include <time.h> #include <sys/stat.h> #pragma comment(lib, "ws2_32.lib") /* 函数名:getFileSizeSystemCall(char * strFileName) 功能:获取指定文件的大小 参数: strFileName (char *):文件名 返回值: size (int):文件大小 */ int getFileSizeSystemCall(char * strFileName) { struct stat temp; stat(strFileName, &temp); return temp.st_size; } int getFileSize(char * strFileName){ FILE *fp; int size; if ((fp = fopen(strFileName,"rb")) == NULL) { printf("File open error\n"); return 0; } fseek(fp,0L,SEEK_END); size = ftell(fp); fclose(fp); return size; } void RecvFile(SOCKET sock,char *filename); void main(void) { WSADATA wsaData; SOCKET s; SOCKADDR_IN ServerAddr; int Port = 5151; // char msg1[128]; // char msg2[128]; WSAStartup(MAKEWORD(2,2), &wsaData); // 创建一个新的Socket来连接服务器 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 填写客户端地址信息 // 端口为5150 // 服务器IP地址为"136.149.3.29",注意使用inet_addr将IP地址转换为网络格式 ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(Port); ServerAddr.sin_addr.s_addr = inet_addr("10.160.17.141");//192.168.1.103 // 向服务器发出连接请求 if ( connect(s, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) { printf("Connection Error....\n"); return ; } printf("Connectd....\n"); // recv(s,msg1,sizeof(msg1),0); // recv(s,msg2,sizeof(msg2),0); // printf("msg = %s\n",msg1); // printf("msg = %s\n",msg2); RecvFile(s,"G:\\test.rmvb"); // 新的连接建立后,就可以互相通信了,在这个简单的例子中,我们直接关闭连接, // 并关闭监听Socket,然后退出应用程序 closesocket(s); // 释放Windows Socket DLL的相关资源 WSACleanup(); getchar(); } void RecvFile(SOCKET sock,char *filename){ FILE *fp;//文件指针 char buf[8192];//缓冲区 int filesize ; int blocks; int i; int res; int count ; printf("开始接收文件..\n"); //接收文件大小 recv(sock,(char *)&filesize,sizeof(filesize),0); printf("接收文件大小: %d\n",filesize); fp = fopen(filename,"wb+"); if (fp == NULL) { printf("Client...文件打开错误..\n"); exit(1); } //接收数据 blocks = filesize / sizeof(buf) + 1; printf("块大小: %d\n",blocks); for (i=0; i<blocks;++i) { //清空缓冲区 memset(buf,0,sizeof(buf)); //接收数据 res = recv(sock,buf,sizeof(buf),0); //写入数据 count = fwrite(buf,sizeof(buf),1,fp); printf("第 %d 次是否写入: %d\n",i+1,count); printf("第 %d 次接收: %d\n", i+1,res); } //关闭文件 fclose(fp); }