linux环境下,实现公共聊天室功能
目錄
- 1.題目
- 2.運(yùn)行截圖
- 3.總體設(shè)計(jì)
- 4.詳細(xì)設(shè)計(jì)
- 5.問題描述
- 6.源碼
- 6.1服務(wù)端
- 6.2客戶端
1.題目
- 實(shí)現(xiàn)公共聊天室的程序,在此環(huán)境下允許多個(gè)用戶同時(shí)進(jìn)行聊天;
- 實(shí)現(xiàn)點(diǎn)到點(diǎn)的聊天應(yīng)用,在此環(huán)境下應(yīng)實(shí)現(xiàn)某一用戶到另外一個(gè)用戶的聊天功能;
- 在圖形界面的環(huán)境下進(jìn)行實(shí)現(xiàn)(不做圖形界面的要求);
- 允許多個(gè)用戶同時(shí)進(jìn)行聊天(聊天室環(huán)境下);
- 以u(píng)nix或類unix的C程序完成上述功能;
- Server端應(yīng)該是充分并發(fā)的;
2.運(yùn)行截圖
3.總體設(shè)計(jì)
本程序分為服務(wù)端和客戶端,其中公共聊天室的功能需要客戶端和服務(wù)端都打開,而雙人聊天室只需要打開客戶端即可,并不需要服務(wù)端,通信協(xié)議都是采用TCP。
先來說說公共聊天室:客戶端通過連接服務(wù)器后利用fork添加一個(gè)子進(jìn)程,利用子進(jìn)程用來往服務(wù)端發(fā)送信息,而父進(jìn)程用來實(shí)時(shí)監(jiān)聽收到的信息并輸出顯示。而對(duì)于服務(wù)端,通過進(jìn)程執(zhí)行while循環(huán)用來監(jiān)聽所有的客戶端連接請(qǐng)求,利用客戶端信息結(jié)構(gòu)體保存連接的客戶端的套接字描述符以及客戶端名字,當(dāng)一個(gè)接收來自客戶端的連接請(qǐng)求之后,利用pthread_create函數(shù)產(chǎn)生一個(gè)線程用來專屬服務(wù)這個(gè)客戶,并往這個(gè)線程里面?zhèn)魉涂蛻舳诵畔⒔Y(jié)構(gòu)體。在這個(gè)線程里面接收來自這個(gè)客戶端的信息并檢查是否是普通信息還是退出聊天的請(qǐng)求,若是退出則相應(yīng)的連接客戶端數(shù)目減1,否則向所有連接的客戶端進(jìn)行廣播這個(gè)信息。
再來說說雙人聊天室:通過客戶端的菜單進(jìn)入雙人聊天室,可以選擇等待別人發(fā)起聊天還是發(fā)起聊天,若選擇等待別人發(fā)起對(duì)自己的聊天則此時(shí)它就相當(dāng)于服務(wù)端,當(dāng)其它客戶端選擇發(fā)起聊天時(shí),則兩者都通過雙進(jìn)程實(shí)現(xiàn)同時(shí)發(fā)送信息,同時(shí)接收信息的功能,當(dāng)一方退出聊天時(shí)候另一方也同時(shí)退出聊天。
4.詳細(xì)設(shè)計(jì)
服務(wù)端:通過define定義服務(wù)端口以及服務(wù)端的最大客戶端連接數(shù)目,接著是定義客戶體信息結(jié)構(gòu)體,包含客戶端的套接字描述符以及客戶端名,還定義一個(gè)服務(wù)器當(dāng)前連接的客戶端數(shù)目的變量client_number。然后是向所有連接服務(wù)器的進(jìn)行廣播信息的函數(shù):其實(shí)就是通過循環(huán)體利用客戶端信息結(jié)構(gòu)體里面的各個(gè)客戶端套接字描述符把消息發(fā)往各個(gè)客戶端當(dāng)中,實(shí)現(xiàn)群聊模式。
而客戶端信息處理函數(shù)就是將發(fā)送的信息的客戶端的名字以及服務(wù)端接收到的信息利用strcat連接起來,然后調(diào)用廣播函數(shù)broadcast將消息發(fā)送給除了發(fā)送的這條信息的客戶端廣播該信息。在這之前利用strncmp檢查發(fā)送過來的信息是否是exit,如果是則向所有的連接的客戶端廣播該用戶已經(jīng)下線,并將當(dāng)前連接客戶端數(shù)目減1,同時(shí)將下線的客戶端的IP地址以及端口號(hào)輸出在屏幕上,再利用close函數(shù)關(guān)閉該套接字描述符。
到主函數(shù)部分就是先調(diào)用socket函數(shù)創(chuàng)建套接字然后接著給sockaddr_in結(jié)構(gòu)體各個(gè)參數(shù)設(shè)置對(duì)應(yīng)的值,然后利用bind綁定相關(guān)給套接字接著進(jìn)入listen狀態(tài)。下面的是放在while循環(huán)里面,當(dāng)客戶端請(qǐng)求連接時(shí)候accept并輸出顯示連接客戶端的IP地址以及端口號(hào),調(diào)用廣播函數(shù)向所有用戶說明該用戶已經(jīng)上線,然后利用pthread_create函數(shù)為其創(chuàng)建單獨(dú)的線程,線程的函數(shù)就是前面所說的信息處理函數(shù)并傳入該客戶端的信息結(jié)構(gòu)體。
客戶端:分別利用define定義雙人聊天室服務(wù)端端口號(hào)、公共聊天室服務(wù)器端口號(hào)和公共聊天室服務(wù)器IP地址,由于各個(gè)函數(shù)之間存在相互調(diào)用,所以提前聲明所有函數(shù),包括主菜單、雙人聊天室、雙人聊天室之等待聊天、雙人聊天室之發(fā)起聊天這幾個(gè)函數(shù),之后聲明五個(gè)變量,分別是雙人聊天室之發(fā)起聊天的子進(jìn)程號(hào)(發(fā)送信息)、雙人聊天室之發(fā)起聊天的父進(jìn)程號(hào)(接收信息)、雙人聊天室之等待聊天的子進(jìn)程號(hào)(發(fā)送信息)、和雙人聊天室之等待聊天的父進(jìn)程號(hào)(接收信息)和多人聊天室的父進(jìn)程號(hào)(接收信息),用于退出聊天時(shí)殺死相對(duì)應(yīng)的進(jìn)程。
主菜單就是利用輸入相應(yīng)指令進(jìn)入相應(yīng)的函數(shù),分別是1-進(jìn)入雙人聊天、2-進(jìn)入公共聊天室、3-退出程序,雙人聊天室函數(shù)同樣如此,分別是1-發(fā)起聊天、2-等待聊天、3-返回菜單、4-退出程序。主函數(shù)直接調(diào)用主菜單,若輸入1進(jìn)入雙人聊天,則進(jìn)入到雙人聊天函數(shù),此時(shí)選擇發(fā)起聊天則進(jìn)入雙人聊天室之發(fā)起聊天,首先提示輸入要與之聊天的IP地址,然后開始創(chuàng)建套接字,設(shè)置相應(yīng)參數(shù),然后利用connect函數(shù)連接對(duì)方(當(dāng)然了,此時(shí)對(duì)方應(yīng)該處于listen狀態(tài)),提示輸入你名字,然后把你的名字發(fā)送給對(duì)方,同時(shí)阻塞等待接收對(duì)方發(fā)回來的名字,接著就和對(duì)方進(jìn)入聊天狀態(tài)。利用fork創(chuàng)建進(jìn)程,子進(jìn)程用于發(fā)送信息,父進(jìn)程用于接收信息。子進(jìn)程當(dāng)中輸入要發(fā)送的信息之后會(huì)把自己的名字以及要發(fā)送的信息以及當(dāng)前時(shí)間放在一起發(fā)送給對(duì)方,若發(fā)送的信息是exit則退出聊天并利用kill函數(shù)殺死通過父進(jìn)程號(hào)殺死父進(jìn)程(接收信息的),并退出子進(jìn)程。對(duì)于接收信息的父進(jìn)程,同樣檢測(cè)對(duì)方發(fā)送過來的信息,如果是exit,則父進(jìn)程同樣利用kill以及子進(jìn)程號(hào)殺死子進(jìn)程并退出。
接著說雙人聊天室之等待聊天函數(shù),同樣地創(chuàng)建套接字,設(shè)置相關(guān)參數(shù),利用bind綁定套接字,進(jìn)入listen狀態(tài),若接收到對(duì)方發(fā)來的通信請(qǐng)求則利用accept接收并返回套接字描述符,接著會(huì)利用recv函數(shù)接收對(duì)方發(fā)來的名字,輸入你的名字并發(fā)送給對(duì)方,接著就進(jìn)入如同上面所說的利用雙進(jìn)程進(jìn)行通信了,這里就不再贅述了。
最后說公共聊天室函數(shù):思路基本同上面的一樣,只不過這個(gè)連接的是服務(wù)器,需要在連接之前打開服務(wù)端,然后就是雙進(jìn)程發(fā)送、接收信息了,程序說明到此結(jié)束。
5.問題描述
1、客戶端輸入名字的發(fā)送給對(duì)方,在對(duì)方對(duì)話框中名字顯示正常,但是在這一段
strcpy(msg, “正在和”);
strcat(msg, friend_name);
strcat(msg, “聊天…\n”);
printf("%s", msg);
當(dāng)中,輸出顯示的名字確是有亂碼的,在公共聊天輸入名字的對(duì)應(yīng)部分卻沒有出現(xiàn)這種情況。一開始以為是緩沖區(qū)問題便清除了緩沖區(qū),但是并不是,后來嘗試recv的時(shí)候保存實(shí)際接收的字節(jié)數(shù),并根據(jù)此將該名字的字符串最后一個(gè)加上結(jié)束符‘\0’,問題就解決了,但是依然無法搞明白為什么會(huì)出現(xiàn)前面所說的情況。
2、服務(wù)端處理客戶端信息函數(shù)的檢查客戶端發(fā)送的信息是否是要退出聊天的部分,一開始是無法執(zhí)行strncmp的,通過驗(yàn)證出現(xiàn)顯示信息驗(yàn)證之后發(fā)現(xiàn),recv函數(shù)之后就直接退出了,并沒有執(zhí)行接下來的代碼,檢查之后recv函數(shù)以及相對(duì)應(yīng)的客戶端程序并沒有問題,后來無緣無故就正常了,再也沒有出現(xiàn)過這種情況。
3、之前有嘗試過解決就是不管多人聊天還是雙人聊天,退出聊天之后應(yīng)該是返回主菜單才對(duì),而不是直接退出整個(gè)程序。但是存在的問題是:例如雙人聊天的兩個(gè)進(jìn)程,一個(gè)接收信息一個(gè)發(fā)送信息,當(dāng)發(fā)送信息的部分檢測(cè)到exit之后就要退出這個(gè)進(jìn)程了,然后exit發(fā)送到對(duì)面的時(shí)候,對(duì)面接收該信息的進(jìn)程同樣也退出了,但是問題是還有發(fā)信息用戶的接收信息進(jìn)程以及收信息用戶的發(fā)送進(jìn)程依然沒有退出,若在此情況直接直接調(diào)用主菜單則還是無法輸入指令,并且由于發(fā)送進(jìn)程和接收信息的存在,一方還是可以發(fā)送信息而另一方接收信息。
后來想著直接關(guān)閉套接字就行了吧,但是并沒用,關(guān)閉一個(gè)進(jìn)程的套接字之后另一個(gè)的進(jìn)程的依然可以正常接收信息。也想著通過無名管道來實(shí)現(xiàn)當(dāng)一個(gè)進(jìn)程關(guān)閉時(shí)往管道發(fā)送信息告訴另一個(gè)進(jìn)程,但是接收信息的管道放在哪里呢?若是放在該進(jìn)程里面,則另一個(gè)進(jìn)程沒有退出則管道一直阻塞,會(huì)導(dǎo)致無法接收其他客戶發(fā)送過來的信息。最后實(shí)在沒辦法了就想到利用另一個(gè)進(jìn)程號(hào),當(dāng)這個(gè)進(jìn)程退出時(shí)候就直接順便利用kill把另一個(gè)進(jìn)程也殺掉了,然后整個(gè)程序就退出了。
6.源碼
6.1服務(wù)端
/*《高級(jí)網(wǎng)絡(luò)程序設(shè)計(jì)》課程作業(yè)1.實(shí)現(xiàn)公共聊天室的程序,在此環(huán)境下允許多個(gè)用戶同時(shí)進(jìn)行聊天;2.實(shí)現(xiàn)點(diǎn)到點(diǎn)的聊天應(yīng)用,在此環(huán)境下應(yīng)實(shí)現(xiàn)某一用戶到另外一個(gè)用戶的聊天功能;3.在圖形界面的環(huán)境下進(jìn)行實(shí)現(xiàn)(不做圖形界面的要求);4.允許多個(gè)用戶同時(shí)進(jìn)行聊天(聊天室環(huán)境下);5.以u(píng)nix或類unix的C程序完成上述功能;6.Server端應(yīng)該是充分并發(fā)的;7.源代碼和報(bào)告的提交時(shí)間為2020年7月10日。 此為服務(wù)端*/#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h>#define PORT 8080 //服務(wù)器端口號(hào) #define MAX_CLIENT 100 //服務(wù)器最大連接數(shù)typedef struct Client //客戶信息結(jié)構(gòu)體 {int client_socket_fd;//客戶端套接字描述符char client_name[20];//客戶端名 }Client; Client client[MAX_CLIENT]; int client_number = 0; //服務(wù)器當(dāng)前連接的客戶端數(shù)目//向所有連接服務(wù)器的進(jìn)行廣播信息 void broadcast(char *msg,Client c) {int i;for(i=0; i < client_number; i++){if(client[i].client_socket_fd != c.client_socket_fd){send(client[i].client_socket_fd, msg, strlen(msg), 0);}} }//客戶端信息處理函數(shù) void *pthread(void *arg) {Client c = *(Client*)(arg);while(1){char buf[1024] = {}, tmp[20] = {};strcpy(buf, c.client_name);strcat(buf, ": ");int a = strlen(buf) + 4;strcpy(tmp, buf);strcat(tmp, "exit");recv(c.client_socket_fd, buf + strlen(buf), 1024 - strlen(buf), 0);if(strncmp(tmp, buf, a) == 0){int i;for(i = 0; i < client_number; i++){if(client[i].client_socket_fd == c.client_socket_fd){client[i] = client[client_number - 1];client_number--;struct sockaddr_in addr;//獲取下線的客戶機(jī)的IP和PORTint length = sizeof(addr);getpeername(c.client_socket_fd, (struct sockaddr*)&addr, &length);printf("客戶機(jī)成功下線 IP: %s PORT: %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));strcpy(buf, "您的好友");strcat(buf, c.client_name);strcat(buf, "下線了\n");break;} }broadcast(buf, c);close(c.client_socket_fd);return NULL;}elsebroadcast(buf,c);} }//主函數(shù) int main(void) {int sfd = socket(AF_INET, SOCK_STREAM ,0);if(sfd == -1){perror("socket error");return -1;}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = htonl(INADDR_ANY);socklen_t addrlen = sizeof(addr);int ret = bind(sfd, (struct sockaddr*)(&addr), addrlen);if(ret == -1){perror("bind error");return -1;}if(listen(sfd, MAX_CLIENT) == -1){perror("listen error");return -1;}printf("正在等待客戶機(jī)連接...\n");while(1){struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(sfd, (struct sockaddr*)(&caddr), &len);if(cfd == -1){perror("accept error");return -1;}printf("客戶機(jī)成功連接 IP: %s PORT: %hu\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));char buf[100] = {};recv(cfd, client[client_number].client_name, 20, 0);client[client_number].client_socket_fd = cfd;pthread_t id;strcpy(buf, "你的好友");strcat(buf, client[client_number].client_name);strcat(buf, "上線了\n");broadcast(buf, client[client_number]);ret = pthread_create(&id, NULL, pthread, (void*)(&client[client_number]));client_number++;if(ret != 0){printf("pthread_create error\n");continue;}}return 0; }6.2客戶端
/*《高級(jí)網(wǎng)絡(luò)程序設(shè)計(jì)》課程作業(yè)1.實(shí)現(xiàn)公共聊天室的程序,在此環(huán)境下允許多個(gè)用戶同時(shí)進(jìn)行聊天;2.實(shí)現(xiàn)點(diǎn)到點(diǎn)的聊天應(yīng)用,在此環(huán)境下應(yīng)實(shí)現(xiàn)某一用戶到另外一個(gè)用戶的聊天功能;3.在圖形界面的環(huán)境下進(jìn)行實(shí)現(xiàn)(不做圖形界面的要求);4.允許多個(gè)用戶同時(shí)進(jìn)行聊天(聊天室環(huán)境下);5.以u(píng)nix或類unix的C程序完成上述功能;6.Server端應(yīng)該是充分并發(fā)的;7.源代碼和報(bào)告的提交時(shí)間為2020年7月10日。 此為客戶端*/#include <netdb.h> #include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT0 8888 //雙人聊天室服務(wù)端端口號(hào) #define PORT1 8080 //公共聊天室服務(wù)器端口號(hào) #define IP "192.168.61.154" //公共聊天室服務(wù)器IP地址void Main_menu(); //主菜單 void Double_chatting_room(); //雙人聊天室 void Public_chatting_room(); //公共聊天室 void Double_chatting_room_wait(); //雙人聊天室之等待聊天 void Double_chatting_room_start(); //雙人聊天室之發(fā)起聊天 pid_t double_chatting_room_start_child; //雙人聊天室之發(fā)起聊天的子進(jìn)程號(hào)(發(fā)送信息) pid_t double_chatting_room_start_father;//雙人聊天室之發(fā)起聊天的父進(jìn)程號(hào)(接收信息) pid_t double_chatting_room_wait_child; //雙人聊天室之等待聊天的子進(jìn)程號(hào)(發(fā)送信息) pid_t double_chatting_room_wait_father; //雙人聊天室之等待聊天的父進(jìn)程號(hào)(接收信息) pid_t public_chatting_room_father; //多人聊天室的父進(jìn)程號(hào)(接收信息)//主菜單 void Main_menu() {printf("1、進(jìn)入雙人聊天室\n2、進(jìn)入公共聊天室\n3、退出程序\n你想要:");int i;scanf("%d", &i);if(i == 1)Double_chatting_room();else if(i == 2)Public_chatting_room();elseexit(0); }//雙人聊天室 void Double_chatting_room() {printf("1、發(fā)起聊天\n2、等待聊天\n3、返回菜單\n4、退出程序\n你想要:");int i;scanf("%d", &i);if(i == 1)Double_chatting_room_start();else if(i == 2)Double_chatting_room_wait();else if(i == 3)Main_menu();elseexit(0); }//雙人聊天室之發(fā)起聊天 void Double_chatting_room_start() {char your_name[20], friend_name[20], msg[50], server_ip[20];printf("請(qǐng)輸入對(duì)方IP地址: ");scanf("%s", server_ip);int sfd;//對(duì)方套接字文件描述符struct sockaddr_in addr;if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket error");exit(-1);}addr.sin_family = AF_INET;addr.sin_port = htons(PORT0);addr.sin_addr.s_addr = inet_addr(server_ip);if(connect(sfd, (const struct sockaddr*)(&addr), sizeof(addr)) == -1){perror("connect error");exit(-1);}printf("成功向?qū)Ψ桨l(fā)起聊天...\n");printf("請(qǐng)輸入你的名字: ");scanf("%s", your_name);send(sfd, your_name, strlen(your_name), 0);int l = recv(sfd, friend_name, 20, 0);//接好友發(fā)來的名字strcpy(msg, "正在和");friend_name[l] = '\0';strcat(msg, friend_name);strcat(msg, "聊天...\n");printf("%s", msg);pid_t pid = fork();if(pid == -1){perror("fork error"); exit(-1);}else if(pid == 0)//子進(jìn)程:發(fā)送信息{while(1){char buf[1024], tmp0[1024], tmp1[1024];double_chatting_room_start_child = getpid();strcpy(buf, your_name);strcat(buf, ": ");scanf("%s", tmp0);strcpy(tmp1, tmp0);strcat(buf, tmp0);strcat(buf, " ");time_t timep;//獲取當(dāng)前系統(tǒng)時(shí)間time(&timep);strcat(buf, ctime(&timep));send(sfd, buf, strlen(buf), 0);if(strcmp(tmp1, "exit") == 0){printf("你已經(jīng)退出聊天...\n");kill(double_chatting_room_start_father, SIGKILL);//退出聊天同時(shí)殺死父進(jìn)程break;}}}else//父進(jìn)程:接收信息{while(1){char buf[1024] = {}, tmp[1024] = {};double_chatting_room_start_father = getpid();recv(sfd, buf, 1024, 0);strcpy(tmp, friend_name);strcat(tmp, ": ");strcat(tmp, "exit");if(strncmp(tmp, buf, strlen(tmp)) == 0){printf("%s已退出聊天\n", friend_name);close(sfd);kill(double_chatting_room_start_child, SIGKILL);//對(duì)方退出聊天則殺死子進(jìn)程并退出父進(jìn)程break;}printf("\t%s", buf);}}Main_menu();//返回主菜單 }//雙人聊天室之等待聊天 void Double_chatting_room_wait() {int sfd = socket(AF_INET, SOCK_STREAM ,0);if(sfd == -1){perror("socket error");exit(-1);}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(PORT0);addr.sin_addr.s_addr = htonl(INADDR_ANY);socklen_t addrlen = sizeof(addr);int ret = bind(sfd, (struct sockaddr*)(&addr), addrlen);if(ret == -1){perror("bind error");exit(-1);}if(listen(sfd, 1) == -1){perror("listen error");exit(-1);}printf("正在等待對(duì)方發(fā)起聊天....\n");struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(sfd, (struct sockaddr*)(&caddr), &len);if(cfd == -1){perror("accept error");exit(-1);}printf("已接受來自對(duì)方發(fā)起的聊天...\n");char friend_name[20], your_name[20], msg[50];int l = recv(cfd, friend_name, 20, 0);printf("請(qǐng)輸入你的名字: ");scanf("%s", your_name);send(cfd, your_name, strlen(your_name), 0);strcpy(msg, "正在和");friend_name[l] = '\0';strcat(msg, friend_name);strcat(msg, "聊天...\n");printf("%s", msg);pid_t pid = fork();if(pid == -1){perror("fork error"); exit(-1);}else if(pid == 0)//子進(jìn)程:發(fā)送信息{while(1){char buf[1024], tmp0[1024], tmp1[1024] = {};double_chatting_room_wait_child = getpid();strcpy(buf, your_name);strcat(buf, ": ");scanf("%s", tmp0);strcpy(tmp1, tmp0);strcat(buf, tmp0);strcat(buf, " ");time_t timep;//獲取當(dāng)前系統(tǒng)時(shí)間time(&timep);strcat(buf, ctime(&timep));send(cfd, buf, strlen(buf), 0);if(strcmp(tmp1, "exit") == 0){printf("你已經(jīng)退出聊天...\n");fflush(stdin);kill(double_chatting_room_wait_father, SIGKILL);//退出聊天同時(shí)殺死父進(jìn)程break;}}}else//父進(jìn)程:接收信息{while(1){char buf[1024] = {}, tmp[1024] = {};double_chatting_room_wait_father = getpid();recv(cfd, buf, 1024, 0);strcpy(tmp, friend_name);strcat(tmp, ": ");strcat(tmp, "exit");if(strncmp(tmp, buf, strlen(tmp)) == 0){printf("%s已退出聊天\n", friend_name);close(cfd);kill(double_chatting_room_wait_child, SIGKILL);//對(duì)方退出聊天則殺死子進(jìn)程并退出父進(jìn)程break;}printf("\t%s", buf);}} }//公共聊天室 void Public_chatting_room() {char name[20];pid_t pid;int sfd;//服務(wù)器套接字描述符struct sockaddr_in addr;if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket error");exit(-1);}addr.sin_family = AF_INET;addr.sin_port = htons(PORT1);addr.sin_addr.s_addr = inet_addr(IP);if(connect(sfd, (const struct sockaddr*)(&addr), sizeof(addr)) == -1){perror("connect error");exit(-1);}printf("成功連接服務(wù)器...\n");printf("請(qǐng)輸入你的名字: ");scanf("%s", name);fflush(stdin);send(sfd, name, strlen(name), 0);pid = fork();if(pid == -1){perror("fork error"); exit(-1);}else if(pid == 0)//子進(jìn)程:發(fā)送信息{while(1){char buf[1024], tmp[1024];scanf("%s", buf);strcpy(tmp, buf);strcat(buf, " ");time_t timep;//獲取當(dāng)前系統(tǒng)時(shí)間time(&timep);strcat(buf, ctime(&timep));send(sfd, buf, strlen(buf), 0);if(strcmp(tmp, "exit") == 0){printf("你已退出聊天...\n");close(sfd);kill(public_chatting_room_father, SIGKILL);//退出聊天則殺死父進(jìn)程并退出子進(jìn)程fflush(stdin);break;}}}else//父進(jìn)程:接收信息{public_chatting_room_father = getpid();while(1){char buf[1024] = {};recv(sfd, buf, 1024, 0);printf("\t%s", buf);}} }//主函數(shù) int main(void) {Main_menu();return 0; }總結(jié)
以上是生活随笔為你收集整理的linux环境下,实现公共聊天室功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为了彻底搞清楚数据库 E-R 模型设计,
- 下一篇: 明翰英语教学系列之冠词篇