1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/*server.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFER_SIZE 4096
#define MAX_QUE_CONN_NM 5
#define PORT 6000
//#define MAXSOCKFD 10
#define FILE_NAME_MAX 512
void recv_mul_file(int sockfd);
void* pthread_func(void * arg);
int main(int argc,char* argv[])
{
int sockfd;
int sin_size = sizeof(struct sockaddr);
struct sockaddr_in server_sockaddr, client_sockaddr;
int i = 1;/* 使得重复使用本地地址与套接字进行绑定 */
/*建立socket连接*/
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",sockfd);
/*设置sockaddr_in 结构体中相关参数*/
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_sockaddr.sin_zero), 8);//将内存块(字符串)的前n个字节清零
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
/*绑定函数bind*/
if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr))== -1)
{
perror("bind");
exit(1);
}
printf("Bind success!\n");
/*调用listen函数*/
if (listen(sockfd, MAX_QUE_CONN_NM) == -1)
{
perror("listen");
exit(1);
}
printf("Listening....\n");
recv_mul_file(sockfd);
close(sockfd);
return 0;
}
void recv_mul_file(int sockfd)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET( sockfd, &readfds);
pthread_t tid;
struct sockaddr_in client_sockaddr;
int client_fd, sin_size = sizeof(struct sockaddr);
int MAXSOCKFD = sockfd;
while(1)
{
if(select(MAXSOCKFD + 1,&readfds,NULL,NULL,NULL) > 0)
{
if(FD_ISSET(sockfd,&readfds)>0)
{
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, (socklen_t *)&sin_size)) == -1)
{
perror("accept");
exit(1);
}
pthread_create(&tid, NULL, pthread_func, &client_fd);
}
FD_SET( client_fd, &readfds);
MAXSOCKFD = (MAXSOCKFD > client_fd? MAXSOCKFD:client_fd);
}
}
}
void* pthread_func(void * arg)
{
//recv file imformation
int client_fd;
char buff[BUFFER_SIZE];
char filename[FILE_NAME_MAX];
int count;
bzero(buff,BUFFER_SIZE);
client_fd = *(int *)arg;
printf("recv from client,client_fd = %d\n",client_fd);
count=recv(client_fd,buff,BUFFER_SIZE,0); //把接受到到字符放在长度为BUFFER_SIZE的buff地址上,接收成功返回接收到到字节数目
if(count<0)
{
perror("recv");
exit(1);
}
strncpy(filename,buff,strlen(buff)>FILE_NAME_MAX?FILE_NAME_MAX:strlen(buff));//把filename地址上的内容复制到地址buff上,第三个参数表明复制多少个字节
printf("Preparing recv file : %s\n",filename );
//recv file
FILE *fd=fopen(filename,"wb+"); //告诉函数库,打开的是一个二进制到可写文件,地址在指针filename
if(NULL==fd)
{
perror("open");
exit(1);
}
bzero(buff,BUFFER_SIZE); //缓冲区清0
int length=0;
while(length=recv(client_fd,buff,BUFFER_SIZE,0)) //这里是分包接收,每次接收4096个字节
{
if(length<0)
{
perror("recv");
exit(1);
}
int writelen=fwrite(buff,sizeof(char),length,fd);//把从buff接收到的字符写入(二进制)文件中
if(writelen<length)
{
perror("write");
exit(1);
}
bzero(buff,BUFFER_SIZE); //每次写完缓冲清0,准备下一次的数据的接收
}
printf("Receieved file:%s finished!\n",filename );
fclose(fd);
close(client_fd);
return 0;
}
|