linux-下用c語言編寫的聊天室程序-服務器和客戶端_第1頁
linux-下用c語言編寫的聊天室程序-服務器和客戶端_第2頁
linux-下用c語言編寫的聊天室程序-服務器和客戶端_第3頁
linux-下用c語言編寫的聊天室程序-服務器和客戶端_第4頁
linux-下用c語言編寫的聊天室程序-服務器和客戶端_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、/* server .c* Created on: 2012-6-15* Author: root* /#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <error .h>#include<netinet/in.h>#define PORT

2、7999#define MAX_NUM 3 /client 連接最大個數(shù)#define MAX_CLIENT 15#define MAX_SIZE 1024pthread_rwlock_t idx_lock, wait_lock;/client 信息typedef struct _client int sockfd;char name20;pthread_t pid;int flg; c_client;c_client clientMAX_CLIENT;/ 定義 client;/ 等待的 client struct _client_ int sockfd;char name20;pthread

3、_t pid;struct _client_ *next;typedef struct _client_ c_client_c;等待的c_client_c *head = NULL;c_client_c *temp_c1 = NULL, *temp_c2 = NULL;/ 初始化 client 信息void init_client() int i = 0;for (i = 0; i < MAX_CLIENT; i+) clienti.sockfd = -1;memset(, 0, 20);clienti.pid = -1;clienti.flg = -1;/ 查找

4、結構體數(shù)組中 sockfd 為-1 的下標值int find_fd(c_client *client) int i = 0;while (i < MAX_NUM) / printf("=%dn",clienti.sockfd);if (clienti.sockfd = -1)return i;i+;return -1;/ 判斷登錄格式int logform(char *buf) char *p = strstr(buf, "LOGINrn");int n = strlen(buf);char *q = p + n - 4;if (p != NULL

5、 && p + 7 != q && strcmp(q, "rnrn") = 0)return 1;elsereturn 0;int cmpname(char *buf, c_client *p_client) int i = 0;char *p = strtok(buf + 7, "rnrn");while (clienti.sockfd != -1 && clienti.sockfd != p_client->sockfd && i< MAX_NUM) if (strcmp(c

6、, p) = 0)return 0;i+;return 1;/SHOWvoid showuser(c_client *p_client) int i = 0;char buf1024 = 0 ;strcpy(buf, "200rn");for (i = 0; i < MAX_NUM; i+) if (clienti.sockfd != -1) sprintf(buf + strlen(buf), "%srn", );sprintf(buf + strlen(buf), "rn");s

7、end(p_client->sockfd, buf, strlen(buf), 0);/ALLvoid sendto_all(c_client *p_client, char *buf) int i = 0;char sendbuf1024 = 0 ;sprintf(sendbuf, "AFROMrn%srn%s", p_client->name, buf + 5);for (i = 0; i < MAX_NUM; i+) if (clienti.sockfd != -1 && clienti.flg != -1)if(send(clien

8、ti.sockfd, sendbuf, strlen(sendbuf), 0) <= 0) printf("send errrrrrn");exit(1);int findname(char *name) int i = 0;for (i = 0; i < MAX_NUM; i+) if (clienti.sockfd != -1 && strcmp(, name) = 0) return clienti.sockfd;return 0;/TOvoid sendto_one(c_client *p_client, char

9、 *buf) int i = 0;char sendbuf1024 = 0 ;char name20 = 0 ;char *p = strtok(buf + 4, "rn");/TOrn: 4 個字符后取出 rn 前的名字strcpy(name, p);int sock = findname(name);if (!sock) sprintf(sendbuf, "ERROR2rn%s 用戶不存在 rnrn", name);send(p_client->sockfd, sendbuf, strlen(sendbuf), 0); else sprintf

10、(sendbuf, "FROMrn%srn%s", p_client->name, buf + 4 + strlen( name) + 2);if(send(sock, sendbuf, strlen(sendbuf), 0)<=0)printf("send errrrrrn");exit(1);void pthread_fun(void* cclient);/quitvoid quit(c_client *p_client)int i=0;int idx;char buf1024 = 0;c_client_c *temp;printf(&q

11、uot;-%s 退出聊天室n",p_client->name);close(p_client->sockfd);p_client->sockfd = -1;p_client->pid = -1;p_client->flg = -1;sprintf(buf,"NOTICE1rn%s 退出聊天室rnrn",p_client->name);memset(p_client->name,0,20);for(i=0;i<MAX_NUM;i+)if(clienti.sockfd != -1 && clienti.f

12、lg != -1)send(clienti.sockfd,buf,strlen(buf),0);if(head != NULL && head->next != NULL)memset(buf,0,1024);pthread_rwlock_rdlock(&idx_lock);idx = find_fd(client);pthread_rwlock_unlock(&idx_lock);clientidx.sockfd = head->next->sockfd;pthread_rwlock_wrlock(&wait_lock);temp =

13、 head->next;head->next = head->next->next;free(temp);pthread_rwlock_unlock(&wait_lock);sprintf(buf,"NOTICErn 您已被喚醒,請繼續(xù)操作rnrn");send(clientidx.sockfd,buf,strlen(buf),0);*)if (pthread_create(&clientidx.pid, NULL, (void *)pthread_fun,(void &clientidx) != 0) perror(&quo

14、t;pthread_create");exit(1);pthread_detach(clientidx.pid);void pthread_fun(void* cclient) c_client *p_client = (c_client *) cclient;char bufMAX_SIZE = 0 ;char sendbuf1024 = 0 ;int i, n;char *p;sprintf(sendbuf, "%s", "NOTICErn 通訊通道開啟 rnrn");if (send(p_client->sockfd, sendbu

15、f, strlen(sendbuf), 0) <= 0) printf("send errn");memset(sendbuf, 0, 1024);while (1) memset(buf, 0, MAX_SIZE);n = recv(p_client->sockfd, buf, sizeof(buf) - 1, MSG_NOSIGNAL);if (n <= 0) close(p_client->sockfd);p_client->sockfd = -1;break;if (logform(buf) if (cmpname(buf, p_cli

16、ent) = 0) send(p_client->sockfd, "ERRORrn 用戶名重復rnrn", 26, 0);continue; else p_client->flg = 1;p = strtok(buf + 7, "rnrn");strcpy(p_client->name, p);sprintf(sendbuf, "100rn%srnrn", p_client->name);send(p_client->sockfd, sendbuf, sizeof(sendbuf), 0);printf(

17、"%s 進入聊天室 n", p_client->name);for (i = 0; i < MAX_NUM; i+) if (clienti.sockfd != -1 && clienti.sockfd!= p_client->sockfd && clienti.flg != -1)send(clienti.sockfd, sendbuf, sizeof(sendbuf), 0);memset(sendbuf, 0, 1024);while (1) memset(buf, 0, MAX_SIZE);if (n = recv(

18、p_client->sockfd, buf, MAX_SIZE, 0) <= 0) perror("recv err");break;/printf("recv=%sn",buf);if (p = strstr(buf, "rnrn") != NULL && *(p + 4)= '0') if (!strncmp(buf, "SHOWrnrn", 8) showuser(p_client);/ 客端執(zhí)行show 后,發(fā)送給客端已連接的用continue;if (!strn

19、cmp(buf, "ALLrn", 5) sendto_all(p_client, buf); continue;if (!strncmp(buf, "TOrn",4) sendto_one(p_client, buf); continue;if (!strncmp(buf, "QUITrnrn", 8) quit(p_client);/break;pthread_exit(NULL); else send(p_client->sockfd, "ERRORrn 信 息 不 符 合 協(xié) 議 要 求 rnrn",

20、38, 0); else send(p_client->sockfd, "ERRORrn 未 登 錄 , 請 您 登 錄 再 進 行 其 他 操 作 rnrn", 56, 0);pthread_exit(NULL); int main() int ser_sockfd, clt_sockfd;struct sockaddr_in addr;int idx;char buf1024 = 0 ;/ pthread_rwlock_t idx_lock,wait_lock;pthread_rwlock_init(&idx_lock, NULL);pthread_rwl

21、ock_init(&wait_lock, NULL);init_client();/ 創(chuàng)建服務器 sockfdif (ser_sockfd = socket(AF_INET , SOCK_STREAM, 0) = -1) perror("socket");exit(1);/ 設置服務器網(wǎng)絡地址bzero(&addr , sizeof(addr);addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr .s_addr = htonl(INADDR_ANY);/ 設置端口可重用int

22、 opt = 1;setsockopt(ser_sockfd, SOL_SOCKET , SO_REUSEADDR, &opt, sizeof(opt);/ 將套接字綁定到服務器的網(wǎng)絡地址上if (bind(ser_sockfd, (struct sockaddr*)&addr , sizeof(addr) = -1) perror("bind");exit(1);printf("bind successn");/監(jiān)聽連接請求-監(jiān)聽隊列長度為10if (listen(ser_sockfd, 10) = -1) perror("l

23、isten");exit(1);printf("listen successn");while (1) if (clt_sockfd = accept(ser_sockfd, NULL, NULL) = -1) perror("accept");exit(1);pthread_rwlock_rdlock(&idx_lock);idx = find_fd(client);/ printf("idx=%dn",idx);pthread_rwlock_unlock(&idx_lock);if (idx != -1)

24、 / 連接末滿clientidx.sockfd = clt_sockfd;if (pthread_create(&clientidx.pid, NULL,(void *) pthread_fun,(void *)&clientidx) != 0) perror("pthread_create");exit(1);pthread_detach(clientidx.pid); else / 連接已滿 ,等待temp_c1 = (c_client_c *) malloc(sizeof(c_client_c);temp_c1->sockfd = clt_soc

25、kfd;temp_c1->next = NULL;pthread_rwlock_wrlock(&wait_lock);if (head = NULL) head = (c_client_c *) malloc(sizeof(c_client_c);head->next = temp_c1; else for (temp_c2 = head; temp_c2->next != NULL; temp_c2=temp_c2->next);temp_c2->next = temp_c1;pthread_rwlock_unlock(&wait_lock);m

26、emset(buf, 0, 1024);sprintf(buf, "NOTICErn 服務器已滿,請等候 rnrn");/ 客戶端接受 則等待if (send(temp_c1->sockfd, buf, strlen(buf), 0) <= 0) printf("sendr errn");/* client.c* Created on: 2012-6-18* Author: root* /#include <stdio.h>#include <stdlib.h>#include <string.h>#inc

27、lude <sys/socket.h>#include <unistd.h>#include <sys/types.h>#include <pthread.h>#include <netinet/in.h>#include <error .h>#include <arpa/inet.h>#include <termios.h>#define MAX_SIZE 1024#define PORT 7999static int FLAGE = -1;char name20 = 0;void fun_sho

28、w(int sockfd)char sendbuf256 = 0;sprintf(sendbuf,"SHOWrnrn");if(send(sockfd,sendbuf,strlen(sendbuf),0)<=0)printf("send errn");close(sockfd);exit(1);void fun_all(int sockfd)char sendbufMAX_SIZE = 0;sprintf(sendbuf,"ALLrn",5);printf(" 輸入發(fā)送的內容:n");scanf("

29、%s",sendbuf+5);sprintf(sendbuf+strlen(sendbuf),"rnrn");if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0) printf("send errn");close(sockfd);exit(1);void fun_one(int sockfd)char sendbufMAX_SIZE = 0;char name320 = 0;printf(" 輸入聊天對象:");scanf("%s",name3);spri

30、ntf(sendbuf,"TOrn%srn",name3);printf(" 輸入聊天內容:n");scanf("%s",sendbuf+strlen(sendbuf);sprintf(sendbuf+strlen(sendbuf),"rnrn");if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0) printf("send errn");close(sockfd);exit(1);void fun_quit(int sockfd)char se

31、ndbuf256 = "QUITrnrn"if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0)printf("send errn");close(sockfd);exit(1);void *pthread_fun(int *sock)int sockfd = *sock;char recvbuf1024 = 0;int n = 0;char *p,*q;char name220 = 0;while(1)memset(recvbuf,0,1024);n = recv(sockfd,recvbuf,sizeof

32、(recvbuf),0);if(n<=0)printf("recv failedn");exit(1);if(!strncmp(recvbuf,"NOTICErn 通訊通道開啟 rnrn",30) printf(" 通訊通道開啟 n"); FLAGE=1;if (!strncmp(recvbuf, "100rn", 5) char *p = strtok(recvbuf + 5, "rnrn");/100rn: 3 個字符后取出 rnrn前的名字strcpy(name2, p);print

33、f("NOTICE%s 進入聊天室 n", name2);FLAGE = 4;if (!strncmp(recvbuf, "ERRORrn 用戶名重復rnrn", 26) printf(" 用戶名重復n");FLAGE = 3;if (!strncmp(recvbuf, "200rn", 5) p = strtok(recvbuf+5,"rnrn");while(p != NULL)printf("%sn",p);p = strtok(NULL,"rnrn"

34、;);printf("please input con:n");if(!strncmp(recvbuf,"AFROMrn",7)/printf("recvbuf=%sn",recvbuf);p = strtok(recvbuf+6,"rn");q = strtok(NULL,"rnrn");printf("(%s) 群聊 :%sn",p, q);printf("please input con:n");if(!strncmp(recvbuf,"F

35、ROMrn",6)p = strtok(recvbuf+6,"rn");q = strtok(NULL,"rnrn");printf("(%s) 私聊 (%s):%sn",p,name,q);printf("please input con:n");if(!strncmp(recvbuf,"ERROR2rn",8)p = strtok(recvbuf + 8, "rn");printf("%sn", p);if(!strncmp(recvbuf,

36、"NOTICE1rn",9)p = strtok(recvbuf + 9, "rn");printf(" 用戶 %sn", p);if(!strncmp(recvbuf,"NOTICErn 服務器已滿,請等候 rnrn",37)printf(" 服務器已滿,請等候 n");FLAGE = 0;if(!strncmp(recvbuf,"NOTICErn 您已被喚醒,請繼續(xù)操作rnrn",45)printf(" 你已經(jīng)被喚醒,請繼續(xù)操作 n");FLAGE =

37、 2;int main(int argc,char *argv)if(argc != 2)printf("input server ip:n");exit(1);pthread_t pid;int sockfd;struct sockaddr_in addr;char recvbuf1024 = 0;char sendbuf1024 = 0;int k=0;int n;char str6 = 0;char *p,*q;if(sockfd = socket(AF_INET ,SOCK_STREAM,0) = -1)perror("socket");exit

38、(1);bzero(&addr ,sizeof(addr);addr.sin_family = AF_INET;addr.sin_port = htons(PORT);if(inet_pton(AF_INET ,argv1,(void *)&addr .sin_addr) <= 0)perror("inet_pton");exit(1);/ inet_aton(argv1, &addr .sin_addr);if(connect(sockfd,(struct sockaddr *)&addr ,sizeof(addr) = -1)perror("connect");exit(1);printf("connect successn");/ pid = fork();pthread_create(&pid,NULL,(void *)pthread_fun,(void*)&sockfd);pthread_detach

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論