客户端与服务器间的文件互传
基于socket的文件数据互传,将文件中所有的字符一一通过buf进行传递,为了更好地判断文件的 结束,通过添加文件结束标识符“#”,当接收端接收到该字符,即可表示发送端对该文件传输结束,结束端需要对文件进行保存,并继续创建新的文件进行新文件内容的写入
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include "wrap.h"
#define MAXLINE 20
#define INET_ADDRSTRLEN 16
#define SERV_PORT 6666
char str1[]="cfile/";
const char str2[]="sfile/";
struct s_info{
struct sockaddr_in cliaddr;
int connfd;
};
struct s_info_client{
struct sockaddr_in servaddr;
int sockfd;
};
struct argv_com{
char *argv1;
char *argv2;
};
int *creatfile(char *filename)
{
FILE *fd=fopen(filename,"w+");
if(fd!=NULL){
printf("%s is created.\n",filename);
return (int *)fd ;
}
else{
printf("%s create failed.\n",filename);
return NULL;
}
}
void *server_send(void* server_send)
{
struct s_info *ts_back=(struct s_info*)server_send;
char buf[MAXLINE];
char bufname[MAXLINE];
char str[INET_ADDRSTRLEN];
int send_fd;
send_fd = Socket(AF_INET,SOCK_DGRAM,0);
int on=1;
setsockopt(send_fd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
struct sockaddr_in send_addr;
send_addr.sin_family=AF_INET;
send_addr.sin_port=htons(SERV_PORT);
send_addr.sin_addr.s_addr= htonl(INADDR_BROADCAST);
while(1)
{
memset(bufname,0,sizeof(buf));
scanf("%s",bufname);
printf("bufname:%s\n ",bufname);
FILE *serfile_fd=fopen(bufname,"r");
if(serfile_fd==NULL){
printf("server file not found.\n");
}else{
sendto(send_fd,bufname,MAXLINE,0,(struct sockaddr *)&send_addr,sizeof(send_addr));
int length=0;
memset(buf,0,sizeof(buf));
while((length=fread(buf,sizeof(char),sizeof(buf),serfile_fd))>0)
{
if(sendto(send_fd,buf,MAXLINE,0,(struct sockaddr *)&send_addr,sizeof(send_addr))<0)
{
printf("send file:%s faile\n.",bufname);
break;
}
memset(buf,0,sizeof(buf));
}
fclose(serfile_fd);
char charflags='#';
sendto(send_fd,&charflags,sizeof(char),0,(struct sockaddr *)&send_addr,sizeof(send_addr));
printf("%s transfer successed.\n",bufname);
}
}
Close(ts_back->connfd);
Close(send_fd);
}
void *server_recv(void* server_recv)
{
struct s_info *ts=(struct s_info*)server_recv;
char buf[MAXLINE];
char bufname[MAXLINE];
char str[INET_ADDRSTRLEN];
int m,n;
char charflags='#';
bool flags=false;
while(1)
{
memset(bufname,0,sizeof(bufname));
m=recv(ts->connfd,bufname,sizeof(buf),0);
if(m==0)
{
break;
}
printf("bufname: %s\n",bufname);
FILE *serfile_fd=(FILE *)creatfile(bufname);
while((n=recv(ts->connfd,buf,sizeof(buf),0))>0)
{
printf("n: %d\n",n);
printf("strlrn(buf): %ld\n",strlen(buf));
printf("%s",buf);
for(int i=0;i<strlen(buf);i++)
{
printf("%c\n",buf[i]);
if(charflags==buf[i])
{
fclose(serfile_fd);
printf("%s get successed.\n",bufname);
flags=true;
break;
}
fputc(buf[i],serfile_fd);
}
if(flags==true)
{break;}
memset(buf,0,sizeof(buf));
fflush(serfile_fd);
}
flags=false;
}
Close(ts->connfd);
}
void *do_server()
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char str[MAXLINE];
int i, n;
pthread_t tid_server_recv,tid_server_send;
struct s_info ts[100];
i=0;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd, 20);
printf("Accepting connections ...\n");
cliaddr_len=sizeof(cliaddr);
while(1)
{
connfd=Accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len);
ts[i].cliaddr=cliaddr;
ts[i].connfd=connfd;
pthread_create(&tid_server_recv,NULL,server_recv,(void*)&ts[i]);
pthread_detach(tid_server_recv);
pthread_create(&tid_server_send,NULL,server_send,(void*)&ts[i]);
pthread_detach(tid_server_send);
i++;
}
}
void *do_work_client(void *client_recv)
{
int m,n;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
char bufname[MAXLINE];
char charflags='#';
bool flags=false;
struct s_info_client *ts=(struct s_info_client *)client_recv;
int radio_fd = Socket(AF_INET,SOCK_DGRAM,0);
int on = 1;
setsockopt(radio_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
struct sockaddr_in recv_addr;
recv_addr.sin_family=AF_INET;
recv_addr.sin_port=htons(SERV_PORT);
recv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bind(radio_fd,(struct sockaddr *)&recv_addr,sizeof(recv_addr));
while(1)
{
memset(bufname,0,sizeof(bufname));
m=recvfrom(radio_fd,bufname,MAXLINE,0,NULL,NULL);
if(m==0)
{
break;
}
printf("bufname: %s\n",bufname);
FILE *clifile_fd=(FILE *)creatfile(bufname);
while((n=recvfrom(radio_fd,buf,MAXLINE,0,NULL,NULL))>0)
{
printf("n: %d\n",n);
printf("strlrn(buf): %ld\n",strlen(buf));
printf("%s",buf);
for(int i=0;i<strlen(buf);i++)
{
printf("%c\n",buf[i]);
if(charflags==buf[i])
{
fclose(clifile_fd);
printf("%s get successed.\n",bufname);
flags=true;
break;
}
fputc(buf[i],clifile_fd);
}
if(flags==true)
{break;}
memset(buf,0,sizeof(buf));
fflush(clifile_fd);
}
flags=false;
}
Close(ts->sockfd);
Close(radio_fd);
}
void *do_client(void *argv)
{
struct sockaddr_in servaddr_client;
char buf[MAXLINE];
char bufname[MAXLINE];
int sockfd;
pthread_t tid_client;
struct argv_com *Argv=(struct argv_com *)argv;
struct s_info_client ts;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr_client, sizeof(servaddr_client));
servaddr_client.sin_family = AF_INET;
inet_pton(AF_INET,"Argv->argv1", &servaddr_client.sin_addr);
servaddr_client.sin_port = htons(atoi(Argv->argv2));
Connect(sockfd,(struct sockaddr *)&servaddr_client, sizeof(servaddr_client));
ts.servaddr=servaddr_client;
ts.sockfd=sockfd;
pthread_create(&tid_client,NULL,do_work_client,(void*)&ts);
pthread_detach(tid_client);
while(1)
{
memset(bufname,0,sizeof(buf));
scanf("%s",bufname);
printf("bufname:%s\n ",bufname);
FILE *clifile_fd=fopen(bufname,"r");
if(clifile_fd==NULL){
printf("client file not found.\n");
}else{
Send(sockfd,bufname,MAXLINE,0);
int length=0;
memset(buf,0,sizeof(buf));
while((length=fread(buf,sizeof(char),sizeof(buf),clifile_fd))>0)
{
if(Send(sockfd,buf,sizeof(buf),0)<0)
{
printf("send file:%s faile\n.",bufname);
break;
}
memset(buf,0,sizeof(buf));
}
fclose(clifile_fd);
char charflags='#';
Send(sockfd,&charflags,sizeof(char),0);
printf("%s transfer successed.\n",bufname);
}
}
Close(sockfd);
}
int main(int argc,char *argv[])
{
pthread_t tid_server,tid_client;
if(argc<3){
printf("Enter SERVER\n");
pthread_create(&tid_server,NULL,do_server,NULL);
pthread_detach(tid_server);
}
else{
struct argv_com ar;
ar.argv1=argv[1];
ar.argv2=argv[2];
pthread_create(&tid_client,NULL,do_client,(void *)&ar);
pthread_detach(tid_client);
}
pthread_exit(0);
return 0;
}
strcat()、strcmp()、strcpy()函数的用法
char *strcat(char *dest,const char *src);
char *strncat(char *dest, const char *src, size_t n);
strcat与strncat都是字符串连接函数,功能上稍有区别: strcat可以把src字符串的全部内容复制到dest字符串后面(此时dst的值发生改变); strncat 把一个字符串指定长度复制到另一个字符串后面,若超过指定长度就复制整个字符串
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
strcmp与strncmp都是用来比较字符串(或比较数数组、字符常量)的,区别在于是否比较指定长度的字符串e
若s1==s2则返回0;
若s1>s2则返回正数;
若s1<s2则返回负数。
即:两个字符串子自左向右逐个字符比较(按ASCII值比较大小),直到出现不同的字符或者遇到’\0‘为止。
strncmp函数是比较指定的size个字符,若s1和s2的前size个字符相同,则返回0
注:针对单个字符的比较,也可以直接用“=/=” 即if(‘A’==‘B’)。
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
dest是指目标字符串指针,src是指源字符串指针。dest与src所指的区域不可重叠,strcpy以’\0‘作为结束标志,dest必须有足够的空间来存放src所包含的字符串(包含结束符NULL),成功执行后返回目标数组指针dest。
strcpy是一种不安全的写法,常用strncpy来替代,其表示将src前n个字符复制到字符串dest,但strncpy不会向dest追加结束标记’\0’,为了避免该问题,strncpy的标准用法(手动添加\0)如下:
strncpy(dest,src,sizeof(dest)-1);
dest[sizeof[dest)-1]=‘\0’;
len=strlen(dest);
针对字符串的复制,也可以使用snprintf()
int snprintf ( char * str, size_t size, const char * format, … );
str——目标字符串;
size——拷贝的字符数;
format——格式化成字符串
若format的字符串长度小于size,则会全部复制到str中;如果格式化后的字符串长度大于等于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。
返回值:
1、如果格式化后的字符串长度小于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;
2、如果格式化后的字符串长度大于等于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。
例:
#include <stdio.h>
int main()
{
char buffer[50];
char* s = "runoobcom";
int j = snprintf(buffer, 6, "%s\n", s);
printf("string:\n%s\ncharacter count = %d\n", buffer, j);
return 0;
}
fgets()、scanf()、gets()函数的用法 及区别
scanf()输入了空格就表示字符串结束,空格后的字符作为下一个输入;gets()函数将接收输入的整个字符串直到遇到换行符为止;
fgets()函数既可以从文件中读入数据,也可以从屏幕中输入一字符串:
fgets(str,n,fp);
读入n-1(最多读入n-1)个字符到str为起始地址的字符串中,第n个字符存放换行符(?)
文件流的读出与写入(fwrite、fread)方法
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值:读或写的记录数,成功时返回的记录数等于nmemb,出错或读到文件末尾时返回的记录 数小于nmemb,也可能返回0。
fread和fwrite用于读写记录,这里的记录是指一串固定长度的字节,比如一个int、一个结构体或者一个定长数组。参数size指出一条记录的长度,而nmemb指出要读或写多少条记录,这些记录在ptr所指的内存空间中连续存放,共占size * nmemb个字节,fread从文件stream中读出size * nmemb个字节保存到ptr中,而fwrite把ptr中的size * nmemb个字节写到文件stream中
socket通信传输下,recv获取后的buf的形式
buf是一个字符数组,根据获取的数据填满每一个buf[i],其中也包括换行符。
sizeof的用法
sizeof()获取数据在内存中所占用的存储空间,以字节为单位进行计数。
int a=10;
int arr=[1,2,3];
char str[]="hello";
int len_a = sizeof(a);
int len_arr = sizeof(arr);
int len_str = sizeof(str)
printf("len_a=%d,len_arr=%d,len_str=%d\n",len_a,len_arr,len_str)
例如:
int arr[]={1,2,3};
for(int i=0;i<(sizeof(arr)/sizeof(int));i++){
printf("%d,",arr[i]);
}
此外:
int* arr = new int[5]{1,2,3,4,5};
cout << sizeof(arr) << endl;
cout << sizeof(*arr) << endl;
|