Linux 下 c 语言 聊天软件

这是我学C语言写的第一个软件,是一个完整的聊天软件,里面包括客户端,和服务器端,可以互现聊天,共享文件,有聊天室等,是一个有TCP和UDP协议的聊天软件,测试过很多次在CENTOS和UBUNTU下都通过,写的简单,但五脏俱全,全部贴出来不保留。运行不了,发信给我,还有个使用指南,我是法语写的,有时间我再写个中文的贴上去。废话不说了,代码来了。

  1. #ifndef CHATHEAD_H_
  2. #define CHATHEAD_H_
  3. #include        <arpa/inet.h>
  4. #include        <dirent.h>
  5. #include        <fcntl.h>
  6. #include        <netdb.h>
  7. #include        <unistd.h>
  8. #include        <errno.h>
  9. #include        <string.h>
  10. #include        <stdio.h>
  11. #include        <stdarg.h>
  12. #include        <signal.h>
  13. #include        <stdlib.h>
  14. #include        <time.h>
  15. #include        <arpa/inet.h>
  16. #include        <netinet/in.h>
  17. #include        <sys/uio.h>
  18. #include        <sys/socket.h>
  19. #include        <sys/shm.h>
  20. #include        <sys/sem.h>
  21. #include        <sys/stat.h>
  22. #include        <sys/time.h>
  23. #include        <sys/types.h>
  24. #include        <sys/wait.h>
  25. #define MAXLINE     8000
  26. #ifndef ASTRING_STRUCT
  27. struct aString{
  28. char string[200];
  29. };
  30. #endif
  31. #ifndef HAVE_MESSAGE_STRUCT
  32. struct chatMessage{
  33. int           statu;
  34. char          type[20],message[1024],contenu[4000];
  35. };
  36. #endif
  37. #ifndef HAVE_bind_STRUCT
  38. struct chatBind{
  39. char       ip[50],nom[20],salon[20];
  40. long int   port;
  41. int        id_socket;
  42. };
  43. #endif
  44. #ifndef HAVE_bind_STRUCT
  45. struct chatInfo{
  46. struct  sockaddr_in     cliaddr;
  47. int                     socket  ;
  48. };
  49. #endif
  50. static void
  51. err_doit(int errnoflag, int error, const char *fmt, va_list ap)
  52. {
  53. char    buf[MAXLINE];
  54. vsnprintf(buf, MAXLINE, fmt, ap);
  55. if (errnoflag)
  56. snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",
  57. strerror(error));
  58. strcat(buf, "/n");
  59. fflush(stdout);     /* in case stdout and stderr are the same */
  60. fputs(buf, stderr);
  61. fflush(NULL);       /* flushes all stdio output streams */
  62. }
  63. void
  64. err_sys(const char *fmt, ...)
  65. {
  66. va_list ap;
  67. va_start(ap, fmt);
  68. err_doit(1, errno, fmt, ap);
  69. va_end(ap);
  70. exit(1);
  71. }
  72. void
  73. err_quit(const char *fmt, ...)
  74. {
  75. va_list     ap;
  76. va_start(ap, fmt);
  77. err_doit(0, errno, fmt, ap);
  78. va_end(ap);
  79. exit(1);
  80. }
  81. #endif /*CHATHEAD_H_*/

上面的是头文件,服务器和客户端都要用的。

  1. #include        "chathead.h"
  2. char * host_name = "127.0.0.255";
  3. int port = 6789;
  4. //struct ip_mreq command;
  5. struct ip_mreqn command;
  6. int loop = 1;
  7. int iter = 0;
  8. int sin_len;
  9. char message[256];
  10. int socket_descriptor;
  11. struct sockaddr_in sin;
  12. struct hostent *server_host_name;
  13. static int sockfd;
  14. static FILE *fp;
  15. struct aString as[30];
  16. int ignoreList(char *string){
  17. int i;
  18. for(i=0;i<30;i++){
  19. //printf("_____/n");
  20. //printf("string %s list %s resultat %d/n",string,as[i].string,strcmp(string,as[i].string)==0);
  21. if(strcmp(string,as[i].string)==0){
  22. return -1;
  23. break;
  24. }
  25. }
  26. return 0;
  27. }
  28. void getMyFichePartage(char *pList){
  29. DIR             *pdir;
  30. struct dirent   *pent;
  31. strcpy(pList,"");
  32. if((pdir=opendir("./partage"))==NULL)
  33. {
  34. fprintf(stderr,"open dir failed./n");
  35. }
  36. while(1){
  37. pent=readdir(pdir);
  38. if(pent==NULL)break;
  39. strcat(pList,"/n");
  40. strcat(pList,pent->d_name);
  41. //fprintf(stderr,"%5d %s/n",pent->d_ino,pent->d_name);
  42. }
  43. closedir(pdir);
  44. }
  45. void delectIgnore(char *p){
  46. int i;
  47. for(i=0;i<29;i++){
  48. if (strcmp(as[i].string,p)==0){
  49. strcpy(as[i].string,"");
  50. printf("UN IGNORE OK./n");
  51. }
  52. //else{
  53. //  printf("PAS TROUVE./n");
  54. //}
  55. }
  56. }
  57. void *copyto(void *arg){
  58. char                sendline[MAXLINE];
  59. struct chatMessage  cm;
  60. int                 source;
  61. register int        k;
  62. char                buf[4000];
  63. int i=0;
  64. while (fgets(sendline,MAXLINE,fp)!=NULL) {
  65. sscanf(sendline,"%10[^:]:%200[^:]:%200[^/n]",cm.type,cm.message,cm.contenu);
  66. cm.statu=1;
  67. if(strcmp(cm.type, "UNIGNORE")==0){
  68. delectIgnore(cm.message);
  69. }else if(strcmp(cm.type, "IGNORE")==0){
  70. printf("IGNORE OK/n");
  71. memcpy(as[i].string,cm.message,sizeof(struct aString));
  72. i=i+1;
  73. }else if(strcmp(cm.type, "FILE")==0){
  74. if((source=open(cm.contenu,O_RDONLY))<0){
  75. perror("Problem sur le source");
  76. }else{
  77. lseek(source,O_WRONLY,-1);
  78. write(sockfd,&cm,sizeof(cm));
  79. while((k=read(source,buf,sizeof(buf)))>0){
  80. sleep(1);
  81. strcpy(cm.contenu,buf);
  82. strcpy(cm.type,"FILELINE");
  83. printf("type est %s/n",cm.type);
  84. printf("contenu est %s/n",cm.contenu);
  85. write(sockfd,&cm,sizeof(cm));
  86. }
  87. printf("ENVOYER FICHE EST TERMINE/n");
  88. close(source);
  89. }
  90. }else{
  91. write(sockfd, &cm, sizeof(cm));
  92. }
  93. }
  94. shutdown(sockfd,SHUT_WR);
  95. return(NULL);
  96. }
  97. void *udpListen(void){
  98. //------udp-------------------------------
  99. while(1){
  100. sin_len = sizeof(sin);
  101. if(recvfrom(socket_descriptor, message, 256, 0,(struct sockaddr *)&sin, &sin_len) == -1) {
  102. perror("recvfrom");
  103. }
  104. printf("SERVEUR:%s/n", message);
  105. sleep(1);
  106. }
  107. if(setsockopt(socket_descriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP, &command, sizeof(command)) < 0) {
  108. // perror("setsockopt:IP_DROP_MEMBERSHIP");
  109. }
  110. //----------------------------------------
  111. }
  112. void str_cli(FILE *fp_arg, int sockfd_arg)
  113. {
  114. pthread_t           tid;
  115. pthread_t           udp;
  116. struct chatMessage  recvChat,returnMsg;
  117. int                 target;
  118. char                nameFile[1024];
  119. char                myListFichier[1024];
  120. int                 source;
  121. char                nomDefiche[1024];
  122. register int        k;
  123. char                buf[4000];
  124. sockfd=sockfd_arg;
  125. fp=fp_arg;
  126. returnMsg.statu=1;
  127. pthread_create(&tid,NULL,copyto,NULL);
  128. pthread_create(&udp,NULL,udpListen,NULL);
  129. while (read(sockfd,&recvChat,sizeof(recvChat))==0){
  130. printf("SERVER SHUTDOWN/n");
  131. exit (-4);
  132. }
  133. while (read(sockfd,&recvChat,sizeof(recvChat))>0){
  134. if(strcmp(recvChat.type, "TELEFILE")==0){
  135. printf("Le utilisateur [%s] a telecharge la ficher [%s]./n",recvChat.message,recvChat.contenu);
  136. strcpy(nomDefiche,"./partage/");
  137. strcat(nomDefiche,recvChat.contenu);
  138. if((source=open(nomDefiche,O_RDONLY))<0){
  139. perror("Problem sur le source");
  140. }else{
  141. lseek(source,O_WRONLY,-1);
  142. strcpy(returnMsg.type,"FILE");
  143. strcpy(returnMsg.message,recvChat.message);
  144. strcpy(returnMsg.contenu,recvChat.contenu);
  145. write(sockfd,&returnMsg,sizeof(returnMsg));
  146. while((k=read(source,buf,sizeof(buf)))>0){
  147. sleep(1);
  148. strcpy(returnMsg.contenu,buf);
  149. strcpy(returnMsg.type,"FILELINE");
  150. write(sockfd,&returnMsg,sizeof(returnMsg));
  151. }
  152. printf("ENVOYER FICHE EST TERMINE/n");
  153. close(source);
  154. }
  155. }
  156. if(strcmp(recvChat.type, "GETLIST")==0){
  157. getMyFichePartage(myListFichier);
  158. //printf("myListFichier == %s/n",myListFichier);
  159. printf("Le utilisateur %s a pris votre List fichers partage./n",recvChat.message);
  160. strcpy(returnMsg.type,"MSG");
  161. strcpy(returnMsg.message,recvChat.message);
  162. strcpy(returnMsg.contenu,myListFichier);
  163. write(sockfd, &returnMsg, sizeof(returnMsg));
  164. }
  165. if(strcmp(recvChat.type, "INFO")==0){
  166. printf("SERVEUR : contenu %s/n",recvChat.contenu);
  167. }
  168. else if(strcmp(recvChat.type, "MSG")==0 || strcmp(recvChat.type, "FILE")==0 ||strcmp(recvChat.type, "FILELINE")==0){
  169. if(ignoreList(recvChat.message)==0){
  170. if(strcmp(recvChat.type, "FILE")==0){
  171. strcpy(nameFile,"");
  172. strcat(nameFile,recvChat.contenu);
  173. strcat(nameFile,recvChat.message);
  174. printf("nameFile == %s/n",nameFile);
  175. if((target=open(nameFile, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0){
  176. perror("IMPOSSIBLE DE CREE UNE FICHE!!/n");
  177. }
  178. }else if(strcmp(recvChat.type, "FILELINE")==0){
  179. write(target,recvChat.contenu,strlen(recvChat.contenu));
  180. }
  181. printf("CLIENT : message %s,contenu %s/n",recvChat.message,recvChat.contenu);
  182. }else{
  183. printf("IL Y A UNE MESSAGE ETE IGNORE/n");
  184. }
  185. }
  186. }
  187. }
  188. //--------------------------------------------------------------------------------------
  189. int main(int argc, char **argv){
  190. int                 sockfd;
  191. struct sockaddr_in  servaddr;
  192. //-----------------------udp----------------------------------
  193. if((server_host_name = gethostbyname(host_name)) == 0){
  194. perror("gethostbyname");
  195. exit(EXIT_FAILURE);
  196. }
  197. /*bzero(&sin, sizeof(sin));*/
  198. memset(&sin, 0, sizeof(sin));
  199. sin.sin_family = AF_INET;
  200. sin.sin_addr.s_addr = htonl(INADDR_ANY);
  201. sin.sin_port = htons(port);
  202. if((socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
  203. perror("socket");
  204. exit(EXIT_FAILURE);
  205. }
  206. /* 调用bind之前,设置套接口选项启用多播IP支持*/
  207. loop = 1;
  208. if(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0){
  209. perror("setsockopt:SO_REUSEADDR");
  210. exit(EXIT_FAILURE);
  211. }
  212. if(bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0){
  213. perror("bind");
  214. exit(EXIT_FAILURE);
  215. }
  216. /* 在同一个主机上进行广播设置套接口,作用是方便单个开发系统上测试多播IP广播 */
  217. loop = 1;
  218. if(setsockopt(socket_descriptor, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
  219. perror("setsockopt:IP_MULTICAST_LOOP");
  220. exit(EXIT_FAILURE);
  221. }
  222. /* 加入一个广播组。进一步告诉Linux内核,特定的套接口即将接受广播数据*/
  223. //command.imr_multiaddr.s_addr = inet_addr("224.1.1.1");
  224. //command.imr_interface.s_addr = htonl(INADDR_ANY);
  225. command.imr_multiaddr.s_addr   =   inet_addr(host_name);
  226. command.imr_address.s_addr   =   htonl(INADDR_ANY);
  227. command.imr_ifindex      =   2;
  228. if(command.imr_multiaddr.s_addr == -1) {
  229. perror("224.0.0.1 not a legal multicast address");
  230. exit(EXIT_FAILURE);
  231. }
  232. if (setsockopt(socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0){
  233. //perror("setsockopt:IP_ADD_MEMBERSHIP");
  234. }
  235. //--------------------------------------------------------------
  236. if (argc != 2){
  237. printf("problem of argument/n");
  238. exit(-1);
  239. }
  240. if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
  241. printf("problem of socket/n");
  242. exit(-1);
  243. }
  244. bzero(&servaddr, sizeof(servaddr));
  245. servaddr.sin_family = AF_INET;
  246. servaddr.sin_port   = htons(49156);
  247. if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
  248. printf("problem of socket/n");
  249. exit(-1);
  250. }
  251. if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
  252. err_sys("connect error");
  253. str_cli(stdin,sockfd);
  254. exit(0);
  255. }
  1. #include        "chathead.h"
  2. time_t                  ticks;
  3. char                    buff[MAXLINE];
  4. int                     id_Mp;  //id du memore pargage
  5. struct chatBind*        p;
  6. int                     id_of_semid;
  7. int                     id_of_semget;
  8. //------udp-------------------------------
  9. int                     port = 6789;
  10. int                     socket_descriptor;
  11. struct                  sockaddr_in address;
  12. char                    returnList[1024];
  13. static  FILE *fp2;
  14. int checkItem(int count,struct chatBind* cb){
  15. int i;
  16. for (i=0; i<=count;i++){
  17. if(strcmp(cb->nom,(p+i)->nom)==0)
  18. return 0;
  19. }
  20. return 1;
  21. }
  22. int getList(){
  23. int                 ii;
  24. printf("--------------LIST-------------/n");
  25. for (ii=0; ii<=9;ii++){
  26. //if(strcmp((p+ii)->nom,"0")==1){
  27. printf("NOM [%s], SALON [%s],socket id [%d]/n,",(p+ii)->nom,(p+ii)->salon,(p+ii)->id_socket);
  28. strcat(returnList,"NOM:");
  29. strcat(returnList,(p+ii)->nom);
  30. strcat(returnList,",");
  31. strcat(returnList,"SALON:");
  32. strcat(returnList,(p+ii)->salon);
  33. strcat(returnList," | ");
  34. //}
  35. }
  36. strcat(returnList,"/n");
  37. printf("--------------LIST-------------/n");
  38. return 2;
  39. }
  40. void bordcast(char *string){
  41. //-----------------------udp-------------------------------------
  42. if(sendto(socket_descriptor, string, 1024, 0, (struct sockaddr *)&address, sizeof(address)) < 0) {
  43. perror("sendto");
  44. exit(EXIT_FAILURE);
  45. }
  46. //---------------------------------------------------------
  47. }
  48. //oui 1,non 0
  49. int bind_nom_and_ip(struct chatMessage* point,int sockfd){
  50. struct chatBind     cb;
  51. //int               ii;
  52. struct sembuf       sb;
  53. struct semid_ds     ds;
  54. unsigned short      array[100];
  55. int                 count;
  56. int                 returnValeur=0;
  57. unsigned int        len;
  58. struct sockaddr_in  ss;
  59. getpeername(sockfd,(struct sockaddr*)&ss,&len);
  60. cb.id_socket=sockfd;
  61. memcpy(cb.salon,"PUBLIC",sizeof(cb.salon));
  62. memcpy(cb.nom,point->message,sizeof(cb.nom));
  63. cb.id_socket=sockfd;
  64. ds.sem_nsems = 0;
  65. semctl(id_of_semget, 0, IPC_STAT, &ds);
  66. semctl(id_of_semget, 0, GETALL,array);
  67. count=array[0];
  68. if(checkItem(count,&cb)!=0){
  69. memcpy(p+count, &cb, sizeof(struct chatBind));
  70. sb.sem_num = 0;
  71. sb.sem_op = 1;
  72. sb.sem_flg = sb.sem_flg & ~IPC_NOWAIT;
  73. semop(id_of_semget, &sb, 1);
  74. returnValeur=1;
  75. }else{
  76. printf("IP:%s,NOM:%s,SALON:%s,Port:%ld./n",cb.ip,cb.nom,cb.salon,cb.port);
  77. }
  78. /*printf("...LIST..../n");
  79. for (ii=0; ii<=count;ii++){
  80. printf("NOM [%s], IP  [%s], PORT [%d]/n,",(p+ii)->nom,(p+ii)->ip,(p+ii)->port);
  81. }*/
  82. return returnValeur;
  83. }
  84. int getSockbyNom(char* cp){
  85. int     ii;
  86. char    newOne[1024];
  87. strcat(cp,"/n");
  88. sscanf(cp,"%[^/n]",newOne);
  89. for(ii=0; ii<=9;ii++){
  90. //printf("/n TEST    %s  %s  %d",(p+ii)->nom,cp,strcmp((p+ii)->nom, cp));
  91. if(strcmp((p+ii)->nom, newOne)==1){
  92. //printf("id sockfd ///// %d",(p+ii)->id_socket);
  93. return (p+ii)->id_socket;
  94. break;
  95. }
  96. }
  97. return -1;
  98. }
  99. void getNometSalonParSocket(char* cp,int socketId){
  100. int                 ii;
  101. for (ii=0; ii<=20;ii++){
  102. if((p+ii)->id_socket==socketId){
  103. strcat(cp," NOM:");
  104. strcat(cp,(p+ii)->nom);
  105. strcat(cp,",");
  106. strcat(cp,"DANS SALON:");
  107. strcat(cp,(p+ii)->salon);
  108. break;
  109. }
  110. }
  111. }
  112. void getNomParSocket(char* cp,int socketId){
  113. int                 ii;
  114. for (ii=0; ii<=20;ii++){
  115. if((p+ii)->id_socket==socketId){
  116. memcpy(cp,"",sizeof(cp));
  117. //printf("id de socket de la destination est in a fonction %s /n",cp);
  118. //printf("id de socket de la destination est in a fonction (p+ii)->nom %s /n",(p+ii)->nom);
  119. strcat(cp,(p+ii)->nom);
  120. break;
  121. }
  122. }
  123. }
  124. int sendMsg(struct chatMessage* cm,int sockfd){
  125. int         returnf=getSockbyNom(cm->message);
  126. struct      chatMessage crm;
  127. char        a[1024];
  128. printf("cm->message %s",cm->message);
  129. printf("returnf %d",returnf);
  130. if(returnf==-1){
  131. return 4;
  132. }
  133. else{
  134. printf("id de socket de la destination est %d/n",returnf);
  135. getNomParSocket(a,sockfd);
  136. memcpy(crm.type,"MSG",sizeof(crm.type));
  137. memcpy(crm.message,a,sizeof(a));
  138. memcpy(crm.contenu,cm->contenu,sizeof(crm.contenu));
  139. memcpy(a,"",sizeof(a));
  140. write(returnf,&crm,sizeof(crm));
  141. return 3;
  142. }
  143. }
  144. int getIDofPointbySockId(int sockfd){
  145. int pointId;
  146. for (pointId=0; pointId<=20;pointId++){
  147. if((p+pointId)->id_socket==sockfd){
  148. return pointId;
  149. break;
  150. }
  151. }
  152. return -1;
  153. }
  154. /* resussi return 5
  155. * else return 6
  156. */
  157. int changeSalon(struct chatMessage* cm,int sockfd){
  158. if(getIDofPointbySockId(sockfd)==-1){
  159. return 6;
  160. }else{
  161. //change salon
  162. //printf("get id of table %d/n",getIDofPointbySockId(sockfd));
  163. memcpy((p+getIDofPointbySockId(sockfd))->salon,cm->message,sizeof((p+getIDofPointbySockId(sockfd))->salon));
  164. return 5;
  165. }
  166. }
  167. /* resussi return 7
  168. * else return 8
  169. */
  170. int sendMessageSalon(struct chatMessage* cm,int sockfd){
  171. int                   t;
  172. char                  cp[1024];
  173. struct chatMessage    crm;
  174. int                   returnInt=8;
  175. //cherche nom de salon et envoyer une message à chaque socke
  176. for (t=0; t<=20;t++){
  177. if(strcmp((p+t)->salon,cm->message)==0){
  178. getNomParSocket(cp,sockfd);
  179. memcpy(crm.type,"MSG",sizeof(crm.type));
  180. memcpy(crm.message,&cp,sizeof(crm.message));
  181. memcpy(crm.contenu,cm->contenu,sizeof(crm.contenu));
  182. printf("________%d/n",(p+t)->id_socket);
  183. printf("crm.type %s/n",crm.type);
  184. printf("crm.message %s/n",crm.message);
  185. printf("crm.contenu %s/n",crm.contenu);
  186. write((p+t)->id_socket,&crm,sizeof(crm));
  187. memcpy(cp,"",sizeof(cp));
  188. returnInt=7;
  189. }
  190. }
  191. return returnInt;
  192. }
  193. /* si reussi return 9, sinon return 10 */
  194. int envoyerFile(struct chatMessage* cm,int sockfd){
  195. int                 destinationSocket;
  196. char                sourceName[1024];
  197. struct  chatMessage  crm;
  198. //envoyer file
  199. printf("Two done %s /n",cm->type);
  200. destinationSocket=getSockbyNom(cm->message);
  201. printf("destination Socket est %d/n",destinationSocket);
  202. if(strcmp(cm->type, "FILE")==0){
  203. getNomParSocket(sourceName,sockfd);
  204. strcpy(crm.message,sourceName);
  205. strcpy(crm.type,"FILE");
  206. strcpy(crm.contenu,cm->contenu);
  207. write(destinationSocket,&crm,sizeof(crm));
  208. return 9;
  209. }else if(strcmp(cm->type, "FILELINE")==0){
  210. printf("Three done %s /n",cm->type);
  211. printf("destinationSocket est dans Fileline %d/n",destinationSocket);
  212. strcpy(crm.message,sourceName);
  213. strcpy(crm.type,"FILELINE");
  214. strcpy(crm.contenu,cm->contenu);
  215. printf("crm.contenu == %s /n",crm.contenu);
  216. write(destinationSocket,&crm,sizeof(crm));
  217. return 10;
  218. }
  219. return 11;
  220. }
  221. void getMyFichePartage(char *pList){
  222. DIR             *pdir;
  223. struct dirent   *pent;
  224. strcpy(pList,"");
  225. if((pdir=opendir("./partage"))==NULL)
  226. {
  227. fprintf(stderr,"open dir failed./n");
  228. }
  229. while(1){
  230. pent=readdir(pdir);
  231. if(pent==NULL)break;
  232. strcat(pList,"/n");
  233. strcat(pList,pent->d_name);
  234. //fprintf(stderr,"%5d %s/n",pent->d_ino,pent->d_name);
  235. }
  236. closedir(pdir);
  237. }
  238. //12 oui, 13 non
  239. int getListFiche(struct chatMessage* cm,int sockfd){
  240. char        serveurList[1024];
  241. struct      chatMessage  crm;
  242. int         a;
  243. char        nomDuSource[1024];
  244. if(strcmp(cm->message, "SER")==0){
  245. getMyFichePartage(serveurList);
  246. strcpy(crm.message,"");
  247. strcpy(crm.type,"INFO");
  248. strcpy(crm.contenu,serveurList);
  249. printf("Des fichiers partages sous le serveur sont:  %s /n",crm.contenu);
  250. printf("type:  %s /n",crm.type);
  251. printf("sockfd:  %d/n",sockfd);
  252. write(sockfd,&crm,sizeof(crm));
  253. return 12;
  254. }
  255. else{
  256. a=getSockbyNom(cm->message);
  257. getNomParSocket(nomDuSource,sockfd);
  258. if(a!=-1){
  259. strcpy(crm.message,nomDuSource);
  260. strcpy(crm.type,"GETLIST");
  261. strcpy(crm.contenu,"");
  262. printf("nomDuSource:  %s /n",nomDuSource);
  263. printf("type:  %s /n",crm.type);
  264. printf("sockfd:  %d/n",a);
  265. write(a,&crm,sizeof(crm));
  266. return 12;
  267. }
  268. }
  269. return 13;
  270. }
  271. //14 oui, 15 non
  272. int telecharger(struct chatMessage* cm,int sockfd){
  273. struct      chatMessage  crm;
  274. int         a;
  275. char        nomDuSource[1024];
  276. char        nomDefiche[1024];
  277. int                 source;
  278. register int        k;
  279. char                buf[4000];
  280. if(strcmp(cm->message, "SER")==0){
  281. strcpy(nomDefiche,"./partage/");
  282. strcat(nomDefiche,cm->contenu);
  283. strcpy(crm.type,"FILE");
  284. strcpy(crm.message,"_SERVEUR");
  285. strcpy(crm.contenu,cm->contenu);
  286. printf("nomDefiche %s",nomDefiche);
  287. printf("sockfd %d",sockfd);
  288. if((source=open(nomDefiche,O_RDONLY))<0){
  289. perror("Problem sur le source");
  290. }else{
  291. lseek(source,O_WRONLY,-1);
  292. write(sockfd,&crm,sizeof(crm));
  293. while((k=read(source,buf,sizeof(buf)))>0){
  294. sleep(1);
  295. strcpy(crm.contenu,buf);
  296. strcpy(crm.type,"FILELINE");
  297. write(sockfd,&crm,sizeof(crm));
  298. }
  299. printf("ENVOYER FICHE EST TERMINE/n");
  300. close(source);
  301. }
  302. return 14;
  303. }
  304. else{
  305. a=getSockbyNom(cm->message);
  306. getNomParSocket(nomDuSource,sockfd);
  307. if(a!=-1){
  308. strcpy(crm.message,nomDuSource);
  309. strcpy(crm.type,"TELEFILE");
  310. strcpy(crm.contenu,cm->contenu);
  311. printf("nomDuSource:  %s /n",nomDuSource);
  312. printf("type:  %s /n",crm.type);
  313. printf("contenu:  %s /n",crm.contenu);
  314. printf("sockfd:  %d/n",a);
  315. write(a,&crm,sizeof(crm));
  316. return 14;
  317. }
  318. }
  319. return 15;
  320. }
  321. int distinger(struct chatMessage* point,int sockfd){
  322. int returnInt=0;
  323. if(point->statu==1){
  324. printf(" general type %s/n",point->type);
  325. printf(" general message %s/n",point->message);
  326. printf(" general contenu %s/n",point->contenu);
  327. if(strcmp(point->type, "NOUVEAU")==0){
  328. return(bind_nom_and_ip(point,sockfd));
  329. }else if(strcmp(point->type, "LIST")==0){
  330. return(getList());
  331. }else if(strcmp(point->type, "TELE")==0){
  332. return(telecharger(point,sockfd));
  333. }else if(strcmp(point->type, "MSG")==0){
  334. //printf("Type %s  Gen %s  Contenu %s/n",point->type,point->message,point->contenu);
  335. return(sendMsg(point,sockfd));
  336. }else if(strcmp(point->type, "SALON")==0){
  337. return(changeSalon(point,sockfd));
  338. }else if(strcmp(point->type, "MSGS")==0){
  339. return(sendMessageSalon(point,sockfd));
  340. }else if(strcmp(point->type, "FILE")==0 || strcmp(point->type, "FILELINE")==0){
  341. printf("First done %s /n",point->type);
  342. return(envoyerFile(point,sockfd));
  343. }else if(strcmp(point->type, "LISTF")==0){
  344. return(getListFiche(point,sockfd));
  345. }else{
  346. return 100;
  347. }
  348. point->statu=2;
  349. }
  350. return returnInt;
  351. }
  352. void getNometSalonParIPetPort(char* cp,struct sockaddr_in* s){
  353. int                 ii;
  354. for (ii=0; ii<=20;ii++){
  355. if(
  356. strcmp(inet_ntop(AF_INET,&s->sin_addr,buff,sizeof(buff))
  357. ,
  358. (p+ii)->ip)==0
  359. ){
  360. if(ntohs(s->sin_port)==(p+ii)->port)
  361. {
  362. //printf("NOM[%s],SALON[%s]/n",(p+ii)->nom,(p+ii)->salon);
  363. strcat(cp," NOM:");
  364. strcat(cp,(p+ii)->nom);
  365. strcat(cp,",");
  366. strcat(cp,"DANS SALON:");
  367. strcat(cp,(p+ii)->salon);
  368. break;
  369. }
  370. }
  371. }
  372. }
  373. void deleteInfo(int  socketId){
  374. int                 ii;
  375. for (ii=0; ii<=20;ii++){
  376. if((p+ii)->id_socket==socketId){
  377. strcpy((p+ii)->ip,"");
  378. strcpy((p+ii)->nom,"");
  379. strcpy((p+ii)->salon,"");
  380. (p+ii)->id_socket=0;
  381. (p+ii)->port=0;
  382. break;
  383. }
  384. }
  385. }
  386. void str_echo(int sockfd){
  387. ssize_t                 n;
  388. struct chatMessage      cm,returnMessage;
  389. unsigned int            len;
  390. struct sockaddr_in      ss;
  391. int                     distinge;
  392. char                    a[100];
  393. getpeername(sockfd,(struct sockaddr*)&ss,&len);
  394. for ( ; ; ) {
  395. if((n=read(sockfd,&cm,sizeof(cm)))==0) {
  396. getNomParSocket(a,sockfd);
  397. strcat(a," EST PARTI ");
  398. bordcast(a);
  399. printf("%s",a);
  400. memcpy(a,"",100);
  401. deleteInfo(sockfd);
  402. return;
  403. }else{
  404. printf("il y a une nouvelle message/n.");
  405. distinge=distinger(&cm,sockfd);
  406. printf("distinge %d/n",distinge);
  407. if(distinge==0){
  408. memcpy(returnMessage.type,"INFO",1024);
  409. memcpy(returnMessage.contenu,"DESOLE,CE NOM EST OCCUPE/n",1024);
  410. }else if(distinge==1){
  411. memcpy(returnMessage.type,"INFO",1024);
  412. memcpy(returnMessage.contenu,"CE NOM EST ACCEPTE./n",1024);
  413. getNometSalonParSocket(a,sockfd);
  414. strcat(a," EST ARRIVE ");
  415. bordcast(a);
  416. memcpy(a,"",100);
  417. }else if(distinge==2){
  418. memcpy(returnMessage.type,"INFO",1024);
  419. memcpy(returnMessage.contenu,returnList,1024);
  420. memcpy(returnList,"",1024);
  421. }else if(distinge==3){
  422. memcpy(returnMessage.type,"INFO",1024);
  423. memcpy(returnMessage.contenu,"MESSAGE EST ENVOYE/n",1024);
  424. memcpy(returnList,"",1024);
  425. }else if(distinge==4){
  426. memcpy(returnMessage.type,"INFO",1024);
  427. memcpy(returnMessage.contenu,"MESSAGE ENVOYE ECHOC, CAR IL‘Y A PAS DE NOM CORRESPONDANT/n",1024);
  428. }else if(distinge==5){
  429. memcpy(returnMessage.type,"INFO",1024);
  430. memcpy(returnMessage.contenu,"VOUS AVEZ CHANGE LE SALON/n",1024);
  431. }else if(distinge==6){
  432. memcpy(returnMessage.type,"INFO",1024);
  433. memcpy(returnMessage.contenu,"CHANGE LE SALON ECHOC/n",1024);
  434. }else if(distinge==7){
  435. memcpy(returnMessage.type,"INFO",1024);
  436. memcpy(returnMessage.contenu,"MESSAGE EST ENVOYE (SALON) /n",1024);
  437. }else if(distinge==8){
  438. memcpy(returnMessage.type,"INFO",1024);
  439. memcpy(returnMessage.contenu,"MESSAGE ENVOYE ECHOC (SALON)/n",1024);
  440. }else if(distinge==9){
  441. memcpy(returnMessage.type,"INFO",1024);
  442. memcpy(returnMessage.contenu,"FILE ENVOYE COMMENCE (SALON)/n",1024);
  443. }else if(distinge==10){
  444. memcpy(returnMessage.type,"INFO",1024);
  445. memcpy(returnMessage.contenu,"FILE ENVOYE TERMINE (SALON)/n",1024);
  446. }else if(distinge==11){
  447. memcpy(returnMessage.type,"INFO",1024);
  448. memcpy(returnMessage.contenu,"FILE ENVOYE ECHOC (SALON)/n",1024);
  449. }else if(distinge==12){
  450. memcpy(returnMessage.type,"INFO",1024);
  451. memcpy(returnMessage.contenu,"PRENDRE LIST REUSSIR./n",1024);
  452. }else if(distinge==13){
  453. memcpy(returnMessage.type,"INFO",1024);
  454. memcpy(returnMessage.contenu,"PRENDRE LIST DE LA FICHIER ECHOC./n",1024);
  455. }else if(distinge==14){
  456. memcpy(returnMessage.type,"INFO",1024);
  457. memcpy(returnMessage.contenu,"TELECHARGER COMMENCER./n",1024);
  458. }else if(distinge==15){
  459. memcpy(returnMessage.type,"INFO",1024);
  460. memcpy(returnMessage.contenu,"TELECHARGER ECHOC./n",1024);
  461. }else if(distinge==100){
  462. memcpy(returnMessage.type,"INFO",1024);
  463. memcpy(returnMessage.contenu,"COMMANDE INCONNU/n",1024);
  464. }
  465. /*else{
  466. memcpy(returnMessage.type,"INFO",1024);
  467. //memcpy(returnMessage.contenu,"SERVER:CE NOM EST NOT ACCEPTE./n",1024);
  468. memcpy(returnMessage.contenu,"CE NOM EST NOT ACCEPTE./n",1024);
  469. }*/
  470. write(sockfd,&returnMessage,sizeof(returnMessage));
  471. }
  472. }
  473. }
  474. static void* doit(void *arg){
  475. int connfd;
  476. connfd=*((int *)arg);
  477. pthread_detach(pthread_self());
  478. str_echo(connfd);
  479. close(connfd);
  480. return(NULL);
  481. }
  482. void *envoyerMessageParServer(void) {
  483. char                sendline[10];
  484. struct chatMessage  cm;
  485. //while(fgets(sendline,10,fp2)!=NULL)
  486. while(scanf("%s",sendline)){
  487. if(strlen(sendline)>0)
  488. {
  489. sscanf(sendline,"%10[^:]:%200[^:]:%200[^/n]",cm.type,cm.message,cm.contenu);
  490. strcpy(sendline,"");
  491. if(strcmp(cm.type,"INFO")==0){
  492. printf("%s/n",cm.message);
  493. bordcast(cm.message);
  494. printf("VOUS AVEZ BRODCAST UNE MESSAGE./n");
  495. }
  496. }
  497. }
  498. }
  499. int main(int argc, char **argv)
  500. {
  501. int                     listenfd,*iptr;
  502. struct sockaddr_in      servaddr;
  503. socklen_t               clilen;
  504. pthread_t               tid;
  505. struct sockaddr_in      cliaddr;
  506. pthread_t               serveur;
  507. // udp---------------------------------------------------------------------
  508. socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
  509. if (socket_descriptor == -1) {
  510. perror("Opening socket");
  511. exit(EXIT_FAILURE);
  512. }
  513. int   opt   =   1;
  514. int   len   =   sizeof(opt);
  515. setsockopt(socket_descriptor,   SOL_SOCKET,   SO_BROADCAST,   (char   *)&opt,   len);
  516. memset(&address, 0, sizeof(address));
  517. address.sin_family = AF_INET;
  518. address.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  519. address.sin_port = htons(port);
  520. //------------------------------------------------------------------------
  521. id_Mp = shmget(0x213, sizeof(struct chatBind)*30, 0666|IPC_CREAT|IPC_EXCL);
  522. p= (struct chatBind* )shmat(id_Mp, 0, 0);
  523. id_of_semid=2014;
  524. id_of_semget=semget(id_of_semid, 2, 0666|IPC_CREAT|IPC_EXCL);
  525. semctl(id_of_semget, 0, SETVAL, 0);// counter pour le memoire partage
  526. listenfd =socket(AF_INET, SOCK_STREAM, 0);
  527. bzero(&servaddr, sizeof(servaddr));
  528. servaddr.sin_family      = AF_INET;
  529. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  530. servaddr.sin_port        = htons(49156);
  531. bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
  532. listen(listenfd, 1024);
  533. pthread_create(&serveur,NULL,&envoyerMessageParServer,NULL);
  534. for ( ; ; ) {
  535. clilen = sizeof(cliaddr);
  536. iptr=malloc(sizeof(int));
  537. *iptr = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
  538. printf("IL Y A NOUVEAU CLIENT EST ARRIVE IP [ %s], PORT [ %d]./n",
  539. inet_ntop(AF_INET,&cliaddr.sin_addr,buff,sizeof(buff)),
  540. ntohs(cliaddr.sin_port)
  541. );
  542. printf("son id de socket est %d/n",*iptr);
  543. pthread_create(&tid,NULL,&doit,iptr);
  544. }
  545. exit(EXIT_SUCCESS);
  546. }

都在这里了,现在贴一个使用说明哦

Rapport du Réseau

Projet Réseau et Communication

Table des matières

Introduction et Remerciements ....................................... page 1

Analyser du cas ................................................................... page 2

Manuel d‘utilisation ......................................................... page 2-5

Introduction et Remerciements

Le but de ce projet est pour réaliser un logiciel ? chat ? sou la systeme de Linux par la langage ? ? et  ? c++ ? pour mieux comprendre des protocoles connus de l‘internent et vise à mettre en oeuvre des communication entre processus.

Le r?le du serveur qui est s‘occupe transmettre des message entre des clients et aussi offre des fonctions pour des clients.

Le
r?le de client peut rejoindre la discussion et parler avec les autre
par le serveur, il peut parler avec un seul client et aussi parler avec
tous dans le salon. Mais d‘abord ils faut envoyer leur identifiant par
noter que le serveur, il y a nouveau client est arrivé. Le serveur va
vérifier si ce nom est unique ou pas. Une fois que le client est
correctement identifié, il peut alors commencer à envoyer des messages
et recevoir des message par ? Chat ?.

Par ce projet, on a mieux compris les différence entre des protocoles, et compris comment travaille avec ? processus ? sous linux.

C‘est vraiment de la chance pour nous faire la pratique. Et nous remercions sincèrement de notre professeurs pour votre aider.

Analyser du cas

1,Udp ,Tcp ou avec deux?

D‘aborde, le plus importants est choir un protocole pour réaliser le ? chat ?.
TCP ou UDP, on considère le  priorité de TCP est  un protocole de
transport fiable et on peut le utilise pour envoyer des messages et
recevoir des message entre le serveur et des clients,car Le c?té client de la connexion effectue une ouvertureactive en 3 temps (poignée de mains en trois temps).

Mais,
les broadcast ont lieu au niveau des adresses destination : mac et IP
pas au niveau des protocoles . l‘adressage dans ces protocoles se fait
par les ports, il n‘y a pas de port broadcast comme il y a une adresse
broadcast . par contre, UDP peut être transporté dans des paquets
broadcast car il fonctionne en mode non connecté tandis que TCP ne peut
pas être transporté dans des paquets broadcast car il fonctionne en mode
connecté .

On utilise le protocole UDP pour réaliser la fonction de ? broadcast ?,
par exemple le serveur peut envoyer des message à tout les clients
comme des fonctions PARTANTS et utilise le protocole TCP pour prendre
les commandes comme LIST, NOUVEAU, MESSAGE etc.

2,Structure de Message

Le but de ce outil est envoyer des messages et recevoir des messages entre des client, on définit la structure de message ci-dessous:


struct chatMessage {

int statu; //définit le statue de message, lire pas encore lire etc.

char type[20]; //définit le type de message,

char message[1024]; //définit des information de ce message

char contenu[1024]; //contenu de ce message,

};


Tableau 1 chathead.h

Grace à ce structure, on peut très facile de distinguer et traiter des différents messages.

3,Threads et Verrous

A c?te de serveur, on utiles ? thread ? pour connecter avec chaque client, lorsqu‘il y a un client arrive, le serveur traite le connections avec crée un nouveau ? thread ?,
et chaque processus offrent un mécanisme permettant à un processus de
réaliser plusieurs unités d‘exécution de fa?on asynchrone.

Et
on utiles la fonction ? verrous et variables conditionnelles  car les
verrous permettent de partager facilement des données communes
accessibles en lecture et écriture. Par exemple le serveur qui stocke
les base de donnée pour permet des clients communiquer avec serveur par
différence ID de?socket ?,beaucoup de tache travaillent sur un même serveur.

4,La tableau de stockage

on utilise une structure pour attacher un ? Id de socket ?à un vrai nom de utilisateur,lorsqu‘un client arrive, le serveur enregistre ce nom avec son ? socket ?,
et puis lorsqu‘il part, on le supprime avec une fonction qui peut
tester la statue de ce utilisateur, et tous les information sont stocké
par une mémoire partagé. La structure de message ci-dessous:


struct chatBind

{
char ip[50];
// définit IP de chaque client

char nom[20]; // définit nom de ce client correspondant

char salon[20]; // définit ce client dans lequel salon
long int port;
// définit le port de ce utilisateur
int id_socket;
// définit le ID de socket de ce connections
};


Tableau 2 chathead.h

Manuel d‘utilisation

D‘abord,
on démarre le serveur,qui attende des clients arrivent, l‘address de
serveur est local,c‘est-à-dire il est ? 127.0.0.1 ?:


[email protected]:~/workspace/chat$ ./serveur

Et puis on démarre deux clients,et l‘argument de client est l‘address de serveur:


[email protected]:~/workspace/chat$ ./client 127.0.0.1

En
même temps on peut vois à c?te de serveur qui déserte qu‘il a deux
clients arrivent, et imprimer deux phases sur l‘écran,comme au ci-dessous:


[email protected]:~/workspace/chat$ ./serveur

IL Y A NOUVEAU CLIENT EST ARRIVE IP [ 127.0.0.1], PORT [ 45122].

son id de socket est 5

IL Y A NOUVEAU CLIENT EST ARRIVE IP [ 127.0.0.1], PORT [ 45123].

son id de socket est 6

En
suite on enregistre le nom de client par le fonction ? NOUVEAU ? à c?te
de client, ici on enregistre deux client, il s‘appelle AAA, et l‘autre
s‘appelle BBB.

Si
ce nom est unique, il peut recevoir une message par serveur ? SERVEUR :
type INFO ,contenu CE NOM EST ACCEPTE.  ?,si non, il peut recevoir une
message comme ? SERVEUR : CE NOM EST OCCUPE ?.

Lorsque
le nom est accepté, le serveur utiliser la communication de type
BROADCAST à tout le monde.  ?  SERVEUR: NOM:AAA ,DANS SALON:public EST
ARRIVE  ? .Au début tout les clients sont dans le salon ? public ?.


[email protected]:~/workspace/chat$ ./ client 127.0.0.1

NOUVEAU:AAA

SERVEUR : type INFO ,contenu CE NOM EST ACCEPTE.

SERVEUR: NOM:AAA ,DANS SALON:public EST ARRIVE .

SERVEUR: NOM:BBB ,DANS SALON:public EST ARRIVE .

LIST ,liste les noms de tous les participants à la discussion:


[email protected]:~/workspace/chat$ ./ client 127.0.0.1

LIST:

SERVEUR :

NOM:AAA ,SALON:public |

NOM:BBB ,SALON:public |

MESSAGE(MSG) permet d‘envoyer des messages par un client pour d‘autre client, ici client AAA envoie une message au client BBB;


[email protected]:~/workspace/chat$ ./ client 127.0.0.1

MSG:BBB:Bonjour

Et client BBB qui re?oit une message au ci-dessous:


[email protected]:~/workspace/chat$ ./client 127.0.0.1

Tu a re?u une message de AAA, contenu est: Bonjour

? IGNORE ?
fonction permet de client ne recevoir pas des message de quelqu‘un,par
exemple, AAA veut ignorer des message de BBB,il est possible de faire
comme au ci-dessous:


[email protected]:~/workspace/chat$ ./client 127.0.0.1

IGNORE:BBB

IGNORE OK

Lorsque BBB envoie une message à AAA,AAA peut revoie une message comme au ci-dessous:


[email protected]:~/workspace/chat$ ./client 127.0.0.1

IGNORE:BBB

IGNORE OK

IL Y A UNE MESSAGE ETE IGNORE

La commande ? UNIGNORE ? peut enlever le fonction ? IGNORE ?


[email protected]:~/workspace/chat$ ./client 127.0.0.1

UNIGNORE:BBB

UNIGNORE OK

Pour
changer un salon, il est possible de utiliser le commande ? SALON: nom
de salon ?, s‘il a réussi, le serveur réponde une message ?TU A CHANGE LE SALON. ? :


[email protected]:~/workspace/chat$ ./client 127.0.0.1

SALON:MUSIC:

TU A CHANGE LE SALON.

Et
c‘est aussi possible de envoyer à tous dans le même salon par un client,
il faut utiliser le commande,  ? MSGS:nom de salon:votre parole ?, et
tous dans ce salon peut le recevoir.


[email protected]:~/workspace/chat$ ./client 127.0.0.1

MSGS:MUSIC: tu aime la music ou pas...

Pour envoyer une fiche,c‘est possible de faire avec le commande ? FILE: nom : répertoire de fiche ?, comme au ci-dessous:


[email protected]:~/workspace/chat$ ./client 127.0.0.1

FILE:AAA:./test.c

Si
quelque client part, tout le monde peut recevoir une message ? Le
utilisater AAA est parti ?, si le serveur part, tout les utilisateur
peut prendre une message aussi, comme ? SERVEUR SHUTOWN ?.

Et en plus, le serveur peut utiliser une commande pour envoyer une message à tous, au ci-dessous:


[email protected]:~/workspace/chat$ ./serveur

INFO: Le serveur va démarrer dans 30 min.

Pour
lister des fichier des fichiers présents sur le serveur, il permet de
utiliser la commande ? LISTF:SER: ?, et ? TELE:SER:nom de fichier ?pour
la récupérer.


[email protected]:~/workspace/chat$ ./client 127.0.0.1

LISTF:SER:

contenu présent sur le serveur

hello.txt

for.in

god.c

TELE:SER:hello.txt

envoyer terminer.

Pour
lister des fichier des fichiers présents sur un autre client, il permet
de utiliser la commande ? LISTF:nom de client: ?, et ? TELE:nom de
client :nom de fichier ?pour la récupérer.


[email protected]:~/workspace/chat$ ./client 127.0.0.1

LISTF:BBB:

contenu présent sur le BBB

a.txt

b.txt

c.txt

TELE:BBB:a.txt

envoyer terminer.

时间: 2024-10-29 12:20:06

Linux 下 c 语言 聊天软件的相关文章

Linux下C语言多线程,网络通信简单聊天程序

原文:Linux下C语言多线程,网络通信简单聊天程序 功能描述:程序应用多线程技术,可是实现1对N进行网络通信聊天.但至今没想出合适的退出机制,除了用Ctr+C.出于演示目的,这里采用UNIX域协议(文件系统套接字),程序分为客户端和服务端.应用select函数来实现异步的读写操作. 先说一下服务端:首先先创建套接字,然后绑定,接下进入一个无限循环,用accept函数,接受“连接”请求,然后调用创建线程函数,创造新的线程,进入下一个循环.这样每当有一个新的“连接”被接受都会创建一个新的线程,实现

LINUX下C语言编程基础

实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理及语法规范 7. 掌握静态库和动态库的生成 二.实验步骤 1. 快捷键 Ubuntu中: 2. vim VIM是一个非常好的文本编辑器,很多专业程序员使用VIM编辑代码,即使以后你不编写程序,只要跟文本打交道,都应该学学VIM,可以浏览参考一下普通人

UNIX/Linux下C语言的学习路线

一.工具篇 “公欲善其事,必先利其器”.编程是一门实践性很强的工作,在你以后的学习或工作中,你将常常会与以下工具打交道, 下面列出学习C语言编程常常用到的软件和工具. 1.操作系统    在UNIX或Linux系统中学习C很方便,所以在开始您的学习旅程前请先选择一个UNIX或Linux操作系统,目前可供个人免费使用的UNIX或Linux系统有FreeBSD.RedHat Linux.SUSE Linux等,而且在安装包中还提供很多实用的工具,如:gcc, make等. 如果您一直使用Window

linux 下C语言学习路线

转载:http://blog.csdn.net/xdw1985829/article/details/6817403 UNIX/Linux下C语言的学习路线. 一.工具篇 “公欲善其事,必先利其器”.编程是一门实践性很强的工作,在你以后的学习或工作中,你将常常会与以下工具打交道, 下面列出学习C语言编程常常用到的软件和工具. 1.操作系统     在UNIX或Linux系统中学习C很方便,所以在开始您的学习旅程前请先选择一个UNIX或Linux操作系统,目前可供个人免费使用的UNIX或Linux

Linux下C语言执行过程(预处理,编译,汇编,链接,执行)

1.C语言的执行过程包括5个步骤:分别是:预处理,编译,汇编,链接,执行 第一步:编写C源代码,截图如下: 2.预处理,命令为:gcc -E variable.c -o variable.i(这步的作用是文件的展开和宏替换),生成的文件类型是.i类型的. 3.编译:命令为:gcc -S variable.i -o variable.s,这里的.s文件就成了会变语言,截图如下: 4.汇编,命令是:gcc -c variable.s -o variable.o,截图如下: 5,链接:命令:gcc -

Linux下安装php加速软件Xcache

说明: php安装目录:/usr/local/php php.ini配置文件路径:/usr/local/php/etc/php.ini Nginx安装目录:/usr/local/nginx Nginx网站根目录:/usr/local/nginx/html 1.安装xcache cd /usr/local/src #进入软件包存放目录 wget http://xcache.lighttpd.net/pub/Releases/3.2.0/xcache-3.2.0.tar.gz #下载 tar zxv

PSPP:顶替SPSS常用功能的优秀软件, Linux 下的经济学用软件

几个替代SPSS的软体Salstat http://salstat.sourceforge.net/PSPP http://www.gnu.org/software/pspp/pspp.htmlR http://www.r -project.org/Macanova http://www.stat.umn.edu/macanova/ Linux 下的经济学用软件 准备学习经济学拉.windows上有很多的软件,linux上的话可能都比较隐蔽... 下面就总结一下: R - project : h

Linux下C语言使用openssl库进行加密

在这里插一小节加密的吧,使用openssl库进行加密. 使用MD5加密 我们以一个字符串为例,新建一个文件filename.txt,在文件内写入hello ,然后在Linux下可以使用命令md5sum filename.txt计算md5值 ==> b1946ac92492d2347c6235b4d2611184  .虽然写入的是hello这5个字符,但是我们使用命令xxd filename.txt后可以看出文件结尾处会有个0x0a这个回车符.所以在下面的代码中才会有\n. 1 //打开/usr/

Linux下C语言的几道经典面试题

本篇文章整理了几道Linux下C语言的经典面试题,相信对大家更好的理解Linux下的C语言会有很大的帮助,欢迎大家探讨指正. 1.如果在Linux下使用GCC编译器执行下列程序,输出结果是什么? 答案如下: 2.C语言程序不使用任何条件运算符,打印出十次"Hello"? 答案如下: 或是: 3.如果在Linux下使用GCC编译器执行下列程序,输出结果是什么? 答案如下: 4.如果在Linux下使用GCC编译器执行下列程序,输出结果是什么? 答案如下: 5.如果在Linux下使用GCC编