这是我学C语言写的第一个软件,是一个完整的聊天软件,里面包括客户端,和服务器端,可以互现聊天,共享文件,有聊天室等,是一个有TCP和UDP协议的聊天软件,测试过很多次在CENTOS和UBUNTU下都通过,写的简单,但五脏俱全,全部贴出来不保留。运行不了,发信给我,还有个使用指南,我是法语写的,有时间我再写个中文的贴上去。废话不说了,代码来了。
- #ifndef CHATHEAD_H_
- #define CHATHEAD_H_
- #include <arpa/inet.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <time.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <sys/uio.h>
- #include <sys/socket.h>
- #include <sys/shm.h>
- #include <sys/sem.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #define MAXLINE 8000
- #ifndef ASTRING_STRUCT
- struct aString{
- char string[200];
- };
- #endif
- #ifndef HAVE_MESSAGE_STRUCT
- struct chatMessage{
- int statu;
- char type[20],message[1024],contenu[4000];
- };
- #endif
- #ifndef HAVE_bind_STRUCT
- struct chatBind{
- char ip[50],nom[20],salon[20];
- long int port;
- int id_socket;
- };
- #endif
- #ifndef HAVE_bind_STRUCT
- struct chatInfo{
- struct sockaddr_in cliaddr;
- int socket ;
- };
- #endif
- static void
- err_doit(int errnoflag, int error, const char *fmt, va_list ap)
- {
- char buf[MAXLINE];
- vsnprintf(buf, MAXLINE, fmt, ap);
- if (errnoflag)
- snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",
- strerror(error));
- strcat(buf, "/n");
- fflush(stdout); /* in case stdout and stderr are the same */
- fputs(buf, stderr);
- fflush(NULL); /* flushes all stdio output streams */
- }
- void
- err_sys(const char *fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- err_doit(1, errno, fmt, ap);
- va_end(ap);
- exit(1);
- }
- void
- err_quit(const char *fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- err_doit(0, errno, fmt, ap);
- va_end(ap);
- exit(1);
- }
- #endif /*CHATHEAD_H_*/
上面的是头文件,服务器和客户端都要用的。
- #include "chathead.h"
- char * host_name = "127.0.0.255";
- int port = 6789;
- //struct ip_mreq command;
- struct ip_mreqn command;
- int loop = 1;
- int iter = 0;
- int sin_len;
- char message[256];
- int socket_descriptor;
- struct sockaddr_in sin;
- struct hostent *server_host_name;
- static int sockfd;
- static FILE *fp;
- struct aString as[30];
- int ignoreList(char *string){
- int i;
- for(i=0;i<30;i++){
- //printf("_____/n");
- //printf("string %s list %s resultat %d/n",string,as[i].string,strcmp(string,as[i].string)==0);
- if(strcmp(string,as[i].string)==0){
- return -1;
- break;
- }
- }
- return 0;
- }
- void getMyFichePartage(char *pList){
- DIR *pdir;
- struct dirent *pent;
- strcpy(pList,"");
- if((pdir=opendir("./partage"))==NULL)
- {
- fprintf(stderr,"open dir failed./n");
- }
- while(1){
- pent=readdir(pdir);
- if(pent==NULL)break;
- strcat(pList,"/n");
- strcat(pList,pent->d_name);
- //fprintf(stderr,"%5d %s/n",pent->d_ino,pent->d_name);
- }
- closedir(pdir);
- }
- void delectIgnore(char *p){
- int i;
- for(i=0;i<29;i++){
- if (strcmp(as[i].string,p)==0){
- strcpy(as[i].string,"");
- printf("UN IGNORE OK./n");
- }
- //else{
- // printf("PAS TROUVE./n");
- //}
- }
- }
- void *copyto(void *arg){
- char sendline[MAXLINE];
- struct chatMessage cm;
- int source;
- register int k;
- char buf[4000];
- int i=0;
- while (fgets(sendline,MAXLINE,fp)!=NULL) {
- sscanf(sendline,"%10[^:]:%200[^:]:%200[^/n]",cm.type,cm.message,cm.contenu);
- cm.statu=1;
- if(strcmp(cm.type, "UNIGNORE")==0){
- delectIgnore(cm.message);
- }else if(strcmp(cm.type, "IGNORE")==0){
- printf("IGNORE OK/n");
- memcpy(as[i].string,cm.message,sizeof(struct aString));
- i=i+1;
- }else if(strcmp(cm.type, "FILE")==0){
- if((source=open(cm.contenu,O_RDONLY))<0){
- perror("Problem sur le source");
- }else{
- lseek(source,O_WRONLY,-1);
- write(sockfd,&cm,sizeof(cm));
- while((k=read(source,buf,sizeof(buf)))>0){
- sleep(1);
- strcpy(cm.contenu,buf);
- strcpy(cm.type,"FILELINE");
- printf("type est %s/n",cm.type);
- printf("contenu est %s/n",cm.contenu);
- write(sockfd,&cm,sizeof(cm));
- }
- printf("ENVOYER FICHE EST TERMINE/n");
- close(source);
- }
- }else{
- write(sockfd, &cm, sizeof(cm));
- }
- }
- shutdown(sockfd,SHUT_WR);
- return(NULL);
- }
- void *udpListen(void){
- //------udp-------------------------------
- while(1){
- sin_len = sizeof(sin);
- if(recvfrom(socket_descriptor, message, 256, 0,(struct sockaddr *)&sin, &sin_len) == -1) {
- perror("recvfrom");
- }
- printf("SERVEUR:%s/n", message);
- sleep(1);
- }
- if(setsockopt(socket_descriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP, &command, sizeof(command)) < 0) {
- // perror("setsockopt:IP_DROP_MEMBERSHIP");
- }
- //----------------------------------------
- }
- void str_cli(FILE *fp_arg, int sockfd_arg)
- {
- pthread_t tid;
- pthread_t udp;
- struct chatMessage recvChat,returnMsg;
- int target;
- char nameFile[1024];
- char myListFichier[1024];
- int source;
- char nomDefiche[1024];
- register int k;
- char buf[4000];
- sockfd=sockfd_arg;
- fp=fp_arg;
- returnMsg.statu=1;
- pthread_create(&tid,NULL,copyto,NULL);
- pthread_create(&udp,NULL,udpListen,NULL);
- while (read(sockfd,&recvChat,sizeof(recvChat))==0){
- printf("SERVER SHUTDOWN/n");
- exit (-4);
- }
- while (read(sockfd,&recvChat,sizeof(recvChat))>0){
- if(strcmp(recvChat.type, "TELEFILE")==0){
- printf("Le utilisateur [%s] a telecharge la ficher [%s]./n",recvChat.message,recvChat.contenu);
- strcpy(nomDefiche,"./partage/");
- strcat(nomDefiche,recvChat.contenu);
- if((source=open(nomDefiche,O_RDONLY))<0){
- perror("Problem sur le source");
- }else{
- lseek(source,O_WRONLY,-1);
- strcpy(returnMsg.type,"FILE");
- strcpy(returnMsg.message,recvChat.message);
- strcpy(returnMsg.contenu,recvChat.contenu);
- write(sockfd,&returnMsg,sizeof(returnMsg));
- while((k=read(source,buf,sizeof(buf)))>0){
- sleep(1);
- strcpy(returnMsg.contenu,buf);
- strcpy(returnMsg.type,"FILELINE");
- write(sockfd,&returnMsg,sizeof(returnMsg));
- }
- printf("ENVOYER FICHE EST TERMINE/n");
- close(source);
- }
- }
- if(strcmp(recvChat.type, "GETLIST")==0){
- getMyFichePartage(myListFichier);
- //printf("myListFichier == %s/n",myListFichier);
- printf("Le utilisateur %s a pris votre List fichers partage./n",recvChat.message);
- strcpy(returnMsg.type,"MSG");
- strcpy(returnMsg.message,recvChat.message);
- strcpy(returnMsg.contenu,myListFichier);
- write(sockfd, &returnMsg, sizeof(returnMsg));
- }
- if(strcmp(recvChat.type, "INFO")==0){
- printf("SERVEUR : contenu %s/n",recvChat.contenu);
- }
- else if(strcmp(recvChat.type, "MSG")==0 || strcmp(recvChat.type, "FILE")==0 ||strcmp(recvChat.type, "FILELINE")==0){
- if(ignoreList(recvChat.message)==0){
- if(strcmp(recvChat.type, "FILE")==0){
- strcpy(nameFile,"");
- strcat(nameFile,recvChat.contenu);
- strcat(nameFile,recvChat.message);
- printf("nameFile == %s/n",nameFile);
- if((target=open(nameFile, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0){
- perror("IMPOSSIBLE DE CREE UNE FICHE!!/n");
- }
- }else if(strcmp(recvChat.type, "FILELINE")==0){
- write(target,recvChat.contenu,strlen(recvChat.contenu));
- }
- printf("CLIENT : message %s,contenu %s/n",recvChat.message,recvChat.contenu);
- }else{
- printf("IL Y A UNE MESSAGE ETE IGNORE/n");
- }
- }
- }
- }
- //--------------------------------------------------------------------------------------
- int main(int argc, char **argv){
- int sockfd;
- struct sockaddr_in servaddr;
- //-----------------------udp----------------------------------
- if((server_host_name = gethostbyname(host_name)) == 0){
- perror("gethostbyname");
- exit(EXIT_FAILURE);
- }
- /*bzero(&sin, sizeof(sin));*/
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(port);
- if((socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
- perror("socket");
- exit(EXIT_FAILURE);
- }
- /* 调用bind之前,设置套接口选项启用多播IP支持*/
- loop = 1;
- if(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0){
- perror("setsockopt:SO_REUSEADDR");
- exit(EXIT_FAILURE);
- }
- if(bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0){
- perror("bind");
- exit(EXIT_FAILURE);
- }
- /* 在同一个主机上进行广播设置套接口,作用是方便单个开发系统上测试多播IP广播 */
- loop = 1;
- if(setsockopt(socket_descr