这是我学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

Grâce à 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 tâche 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 »:

wei@wei-laptop:~/workspace/chat$ ./serveur

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

wei@wei-laptop:~/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:

wei@wei-laptop:~/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 ».

wei@wei-laptop:~/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:

wei@wei-laptop:~/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;

wei@wei-laptop:~/workspace/chat$ ./ client 127.0.0.1

MSG:BBB:Bonjour

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

wei@wei-laptop:~/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:

wei@wei-laptop:~/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:

wei@wei-laptop:~/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 »

wei@wei-laptop:~/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. » :

wei@wei-laptop:~/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.

wei@wei-laptop:~/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:

wei@wei-laptop:~/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:

wei@wei-laptop:~/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.

wei@wei-laptop:~/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.

wei@wei-laptop:~/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.

转载于:https://www.cnblogs.com/dpf-learn/p/7058783.html

Linux 下 c 语言 聊天软件相关推荐

  1. linux下c语言聊天室程序,纯C语言Socket实现聊天室

    最近在学习嵌入式开发,练习C语言小项目,基本是参考别人的代码,做了些修改实现了聊天室,纯C语言编写. 想直接看源码的跳到最后. 一.练习内容 socket通信流程 管道的使用 epoll的使用 首先要 ...

  2. linux下udp实现聊天软件,socket实现一个简单的对话聊天软件

    socket可以在网络间进行通信, 基本上有两种通信协议, 一种是TCP, 一种是UDP. UDP是一种面向无链接的通信协议, 通信前无需与对端建立连接. 只要有目的ip地址和port端口, 就可以将 ...

  3. linux下多人聊天室

    客户端 一个在Linux下可以使用的聊天软件,要求至少实现如下功能:1. 采用Client/Server架构2. Client A 登陆聊天服务器前,需要注册自己的ID和密码3. 注册成功后,Clie ...

  4. 利用多线程实现linux下C语言的聊天室程序:

    转载:http://www.360doc.com/content/16/0421/11/478627_552531090.shtml 利用多线程实现linux下C语言的聊天室程序: 客户端代码: th ...

  5. Linux环境下——C语言聊天室项目

    由于使用了多线程操作,客户端进入程序后请先随便注册一次用户后再进行使用. 本程序默认第一个用户即ID为1的用户为超级管理员. 由于线程阻塞,最后的踢人操作有阻塞,需要在被踢出在线链表后手动下线. 看了 ...

  6. linux下c语言调用mysql,Linux下C语言连接MySQL

    首先保证安装: 1:安装MySQL:sudo apt-get install mysql-server mysql-client 2:安装MySQL开发包:sudo apt-get install l ...

  7. linux c语言工具,Linux下C语言编程环境的工具.doc

    Linux下C语言编程环境的工具 Linux下C语言编程环境的工具 Linux下C语言编程环境的工具 要想在Linux下进行C语言编程,首先得搭建好一个编程环境.这里分别说明一下几个非常有用的软件包. ...

  8. GCC编译器简明教程(Linux下C语言开发环境的搭建)

    GCC编译器简明教程(Linux下C语言开发环境的搭建) 市面上常见的Linux都是发行版本,典型的Linux发行版包含了Linux内核.桌面环境(例如GNOME.KDE.Unity等)和各种常用的必 ...

  9. 您知道Linux下C语言编程的一些注意事项吗_教育中国

    您知道Linux下C语言编程的一些注意事项吗_教育中国 云风的 BLOG: 一个 C 接口设计的问题 一个 C 接口设计的问题 C 语言在本质上,参数传递都是值传递.不像 Pascal 和 C++ 可 ...

最新文章

  1. (chap1 网络基础知识)网络的构成要素:(7)网关
  2. mysql中如何卸载插件_Eclipse中如何卸载插件
  3. 那些你不知道的 getClientRects()
  4. 设计模式学习笔记——原型(Prototype)框架
  5. myeclipse 中解决Hibernate 和Struts 2的冲突
  6. Python学习教程:Python3内置模块之base64编解码方法小结
  7. Android 2.3 版本中链接边框问题解决
  8. 下一代终端保护六大支柱
  9. linux下升级mysql_linux下mysql升级
  10. c语言程序设计实践教程课后题,《C语言程序设计实践教程》答案-完整版.doc
  11. 2021年中国研究生数学建模竞赛B题参考思路
  12. 密码编码学与网络安全——原理与实践(第八版)------第4章 学习笔记
  13. UWP 如何阻止WebView自动打开浏览器?
  14. 交换机测试丢包软件,交换机丢包问题定位
  15. Effective Modern C++笔记汇总
  16. 【洛谷 2504】聪明的猴子
  17. Thingsboard 项目说明,框架目录结构、技术及部署相关说明
  18. 关于android手游Sdk开发的专题(一)
  19. ssh连接远程服务器自动断开解决
  20. 8-Noise Error

热门文章

  1. jenkins安装,构建第一个工程(更新代码到工作空间)
  2. 欢迎来到 VOXEL WARS!
  3. 【深度学习】扩散模型(Diffusion Model)详解
  4. scihub下载太慢或者无法加载的问题
  5. Python获取桌面路径
  6. C# Unity 访问桌面路径
  7. 实验室LIMS系统能带来什么好处?
  8. niit java证书_NIIT认证Java基础全真模拟试题
  9. 倒手一套房,还贷款后落地400万!我打算离开上海了~
  10. Java开发需要学习哪些知识?初学者怎么学好Java开发?