版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/stone8761/article/details/81027170
程序分为server、client两个部分,client从server获取文件。流程如下:
server:
1、创建socket,绑定端口10002,等待client连接;
2、链接后打开需要发送的文件,计算文件长度并发送长度,等待接收客户端响应;
3、客户端响应ok后,发送文件数据,发送缓冲定位8192;
4、发送结束后关闭链接;
client:
1、创建socket,链接server;
2、接收文件长度,并回复ok;
3、接收数据并写入文件,接收缓冲为8192;
4、接收结束后关闭链接;
参考代码如下:
file_server.c:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define BUF_SIZE (8192)
unsigned char fileBuf[BUF_SIZE];
/*
* send file
*/
void
file_server(const char *path)
{
int skfd, cnfd;
FILE *fp = NULL;
struct sockaddr_in sockAddr, cltAddr;
socklen_t addrLen;
unsigned int fileSize;
int size, netSize;
char buf[10];
if( !path ) {
printf("file server: file path error!\n");
return;
}
//创建tcp socket
if((skfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
} else {
printf("socket success!\n");
}
//创建结构 绑定地址端口号
memset(&sockAddr, 0, sizeof(struct sockaddr_in));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockAddr.sin_port = htons(10002);
//bind
if(bind(skfd, (struct sockaddr *)(&sockAddr), sizeof(struct sockaddr)) < 0) {
perror("Bind");
exit(1);
} else {
printf("bind success!\n");
}
//listen 监听 最大4个用户
if(listen(skfd, 4) < 0) {
perror("Listen");
exit(1);
} else {
printf("listen success!\n");
}
/* 调用accept,服务器端一直阻塞,直到客户程序与其建立连接成功为止*/
addrLen = sizeof(struct sockaddr_in);
if((cnfd = accept(skfd, (struct sockaddr *)(&cltAddr), &addrLen)) < 0) {
perror("Accept");
exit(1);
} else {
printf("accept success!\n");
}
fp = fopen(path, "r");
if( fp == NULL ) {
perror("fopen");
close(cnfd);
close(skfd);
return;
}
fseek(fp, 0, SEEK_END);
fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(write(cnfd, (unsigned char *)&fileSize, 4) != 4) {
perror("write");
close(cnfd);
close(skfd);
exit(1);
}
if( read(cnfd, buf, 2) != 2) {
perror("read");
close(cnfd);
close(skfd);
exit(1);
}
while( ( size = fread(fileBuf, 1, BUF_SIZE, fp) ) > 0 ) {
unsigned int size2 = 0;
while( size2 < size ) {
if( (netSize = write(cnfd, fileBuf + size2, size - size2) ) < 0 ) {
perror("write");
close(cnfd);
close(skfd);
exit(1);
}
size2 += netSize;
}
}
fclose(fp);
close(cnfd);
close(skfd);
}
int
main(int argc, char **argv)
{
if( argc < 2 ) {
printf("file server: argument error!\n");
printf("file_server /tmp/temp\n");
return -1;
}
file_server(argv[1]);
return 0;
}
file_client.c:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define BUF_SIZE (8192)
unsigned char fileBuf[BUF_SIZE];
void
file_client(const char *ip, const char *path)
{
int skfd;
FILE *fp = NULL;
struct sockaddr_in sockAddr;
unsigned int fileSize, fileSize2;
int size, nodeSize;
//创建tcp socket
if((skfd=socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("socket");
exit(1);
} else {
printf("socket success!\n");
}
//创建结构设定待连接的服务器地址端口号
memset(&sockAddr, 0, sizeof(struct sockaddr_in));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(ip);
sockAddr.sin_port = htons(10002);
/* 客户端调用connect主动发起连接请求 */
if(connect(skfd, (struct sockaddr *)(&sockAddr), sizeof(struct sockaddr)) < 0) {
perror("ConnectError:");
exit(1);
} else {
printf("connnect success!\n");
}
size = read(skfd, (unsigned char *)&fileSize, 4);
if( size != 4 ) {
printf("file size error!\n");
close(skfd);
exit(-1);
}
printf("file size:%d\n", fileSize);
if( (size = write(skfd, "OK", 2) ) < 0 ) {
perror("write");
close(skfd);
exit(1);
}
fp = fopen(path, "w");
if( fp == NULL ) {
perror("fopen");
close(skfd);
return;
}
fileSize2 = 0;
while(memset(fileBuf, 0, sizeof(fileBuf)), (size = read(skfd, fileBuf, sizeof(fileBuf))) > 0) {
unsigned int size2 = 0;
while( size2 < size ) {
if( (nodeSize = fwrite(fileBuf + size2, 1, size - size2, fp) ) < 0 ) {
perror("write");
close(skfd);
exit(1);
}
size2 += nodeSize;
}
fileSize2 += size;
if(fileSize2 >= fileSize) {
break;
}
}
fclose(fp);
close(skfd);
}
int
main(int argc, char **argv)
{
if( argc < 3 ) {
printf("file client: argument error!\n");
printf("file_client 192.168.1.10 /tmp/temp\n");
return -1;
}
file_client(argv[1], argv[2]);
return 0;
}
测试结果:
首先启动server端,发送文件mysql-server-8.0.zip
$ ~/tmp/test/fileserver mysql-server-8.0.zip
再启动client端,接收此文件
$ ./fileclient 10.9.0.132 ./mysql.zip
接收成功后解压这个文件测试传输是否成功。