hello kity
期待您的批阅,由于写解题报告时 不一定考虑的很周到,所以如果您有什么不懂的地方,请您留言,然而一天之内我肯定会看见您信息,再对代码注释详细,让您更好的阅读
分类
最新评论
最新留言
链接
RSS
计数器
222863
功能
基于多线程并发 客户/服务器之间传输各种文件问题研发
由于代码很简单不过多分析。这里需要注意几点:
第一:线程的状态,要设置成分离状态(detached)或者pthread_join()亦可。如果不注意这点并发起来 肯定耗尽资源。
第二:读文件的各种细节问题,如打开模式,正确关闭打开的文件。因为并发启动以后,如果存在大量的打开的文件系统会报错,因为系
统允许的最大打开文件数是固定的。
第三:提醒各位注意一下 recv()函数在什么情况下才返回-1? 笔者在写代码的时候 忽然发现了个自己一个BUG。在recv()返回-1的时候我一直让那个线程循环调用recv() 但是,recv()返回-1的时候 不是没读到数据或者简单的读取失败,是对方已经关闭了连接才会返回-1.所以不能循环调用 只能直接退出线程。
/************************************************************************* FileName: rcv_send_serv.c Authour: weizhou Descripthion: create multiple thread to serve for every client Version: 2013/6/1 Function List: SendData() ***************************************************************************/ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <time.h> #include <sys/select.h> #include <arpa/inet.h> #include <signal.h> #include <dirent.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <netinet/tcp.h> #define PORT 28000 #define BACKLOG 5 #define MAXDATASIZE 10000 #define DEBUG 1 #define NAMELEN 40 pthread_mutex_t mutex; pthread_mutex_t guard_gdata; int iThreadCount=1010; /*default htread count*/ char sFilePath[40] = "/home/weizhou/cash/"; int iFileIndex = 1; void *rtx; void* start_routine(void* pArg); int listenfd; int main(int agrc,char *argv[]) { long lConnectFd; pthread_t thread; //id of thread struct sockaddr_in server; //server's address info struct sockaddr_in client; //client's int sin_size; //create tcp socket if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("creating socket failed."); exit(1); } bzero(&server,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) { exit(1); } if(listen(listenfd,BACKLOG) == -1) { exit(1); } sin_size = sizeof(struct sockaddr_in); while(1) { if((( lConnectFd = accept(listenfd, (struct sockaddr *)&client, (socklen_t*)&sin_size))) == -1) { return -1; } if (( pthread_create(&thread, NULL, start_routine, (void*)(lConnectFd))) !=0) { return -1; } } close(listenfd); return 0; } void* start_routine (void* pArg) { FILE * RcvFile; char RcvFileName[40]; int iRcvSize = 0; int iRcvNum; int iConnectFd; char cRcvBuffer[MAXDATASIZE]; iConnectFd = (long)pArg; if (pthread_detach (pthread_self()) != 0) { printf ("pthread_detach run error.\n"); return ; } sprintf (RcvFileName, "%sdemo%d.mp3",sFilePath ,iFileIndex++); if ((RcvFile = fopen (RcvFileName, "wb")) == NULL) { printf ("fail to open %s : %s.\n", RcvFileName, strerror(errno)); printf ("%s\n", strerror(errno)); return ; } while(1) { if ((iRcvNum =recv(iConnectFd, cRcvBuffer, MAXDATASIZE, 0)) == -1) { printf ("recv error:%s.\n", strerror(errno)); fclose (RcvFile); return ; } if (iRcvNum == 0) break; iRcvNum = fwrite (cRcvBuffer, sizeof (char), iRcvNum, RcvFile); iRcvSize += iRcvNum; } fclose(RcvFile); printf ("have writed %d bytes in file.\n", iRcvSize); return; }
/************************************************************************* FileName: rcv_send_cli.c Authour: weizhou Descripthion: create multiple thread send data to server just like client Version: 2013/6/1 Function List: SendData() ***************************************************************************/ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <time.h> #include <sys/select.h> #include <arpa/inet.h> #include <signal.h> #include <dirent.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <netinet/tcp.h> #define MAXSIZE 1024 #define PORTNUMBER 28000 #define MAX_LINE 10000 #define SERNUM 1000 pthread_mutex_t mutex; int iPthreadCount = 0; char sFileName[40]; int GetFileSize(char* StrFileNaem); /*obtain the size of a file */ void *SendData(void *arg); /*the routine function in pthread_creat() */ int main (const int argc, const char **argv) { struct sockaddr_in serv; pthread_mutex_init (&mutex, NULL); int i; if (argc != 3) { printf("Usage: <IpAddress> <filename>\n"); return -1; } bzero (&serv, sizeof(serv)); serv.sin_port = htons (PORTNUMBER); serv.sin_family = AF_INET; if (inet_pton (AF_INET, argv[1], &serv.sin_addr) <= 0) { printf ( "inet_pton error from %s: %s\n", argv[1], strerror(errno) ); return -1; } strncpy (sFileName, argv[2], 30); for (i=0; i<=SERNUM; i++) { pthread_t tempthread_id; sleep(7); while (pthread_create (&tempthread_id, NULL, (void *)SendData, (void*)&serv) != 0) { printf ("create thread error: %s.\n\n", strerror(errno)); } } printf ("the number of thread is %d.\n", iPthreadCount); while(1) { sleep(2); } return 0; } void* SendData(void* arg) { int sockfd; FILE *PSendFile; int iSizeOfFile; int iSizeCount = 0; char SendBuffer[MAX_LINE + 1]; int iSendLen; pthread_detach (pthread_self()); while ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <= 0 ) { printf ("obtain a socket error: %s.\n\n", strerror(errno)); } if (connect (sockfd, (struct sockaddr*)arg, sizeof(struct sockaddr_in)) !=0) { printf ("socket connect error: %s.\n\n", strerror(errno)); return; } /*get the pointer of file, and determin the size of this file */ if ((PSendFile = fopen (sFileName,"rb")) == NULL) { printf("fail to open!: %s\n", strerror(errno)); return ; } while (!feof(PSendFile)) { bzero (SendBuffer, MAX_LINE + 1); iSendLen = fread (SendBuffer, sizeof(char), MAX_LINE, PSendFile); /*printf ("send %d bytes.\n", iSendLen);*/ if ((iSendLen = send (sockfd, SendBuffer, iSendLen, 0)) == -1) { printf ("send error!:%s\n", strerror(errno)); continue; } iSizeCount += iSendLen; } if (fclose(PSendFile) != 0) { printf ("closed error!:%s\n", strerror(errno)); } pthread_mutex_lock (&mutex); iPthreadCount += 1; pthread_mutex_unlock (&mutex); printf ("the data has sended is %d bytes.\n", iSizeCount); close (sockfd); return NULL; }