linux網路程式設計練習---聊天室(TCP/IP實現)
阿新 • • 發佈:2019-01-06
為了更深刻的鍛鍊認識TCP/IP協議,加強自己對Linux系統的網路程式設計部分的編寫程式碼能力,編寫基於控制檯的聊天視窗,用本機既當伺服器又當客戶端,先開啟一個shell,執行伺服器程式,然後再開啟一個shell視窗,執行客戶端程式,顯示連線成功,開始聊天吧。不知道為什麼上傳效果圖不成功,把圖放在相簿了。
/*客戶端*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define BUFFER_SIZE 256 #define PORT 4568 char recv_buff[BUFFER_SIZE]; char send_buff[BUFFER_SIZE]; int main(void) { char write_flag=0; char read_flag=1; int sockfd;// 套結字 struct sockaddr_in cli_addr;//伺服器的IPv4的套結字結構 if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)//建立套結字 { perror("socket"); exit(1); } else { printf("creat client socket success id:%d\n",sockfd); } bzero(&cli_addr,sizeof(struct sockaddr_in)); cli_addr.sin_family=AF_INET; cli_addr.sin_port=htons(PORT); cli_addr.sin_addr.s_addr=htonl(INADDR_ANY); if(connect(sockfd,(struct sockaddr*)(&cli_addr),sizeof(struct sockaddr))<0) { perror("connect"); exit(2); } else { printf("connect server success.\n"); } memset(send_buff,0x00,sizeof(send_buff)); memset(recv_buff,0x00,sizeof(send_buff)); while(1) { if(strlen(send_buff)==0&&write_flag==1)//判斷髮送緩衝區是否為空 { gets(send_buff); if(write(sockfd,send_buff,strlen(send_buff))<0) { perror("write"); exit(3); } else { printf("Client:\n"); printf(" %s\n",send_buff); } read_flag=1; write_flag=0; memset(recv_buff,0x00,strlen(recv_buff)); } else if(strlen(recv_buff)==0&&read_flag==1) { if(read(sockfd,recv_buff,sizeof(recv_buff))<0) { perror("read"); exit(4); } else if(strlen(recv_buff)>0) { printf("server:\n"); printf(" : %s\n",recv_buff); memset(send_buff,0x00,strlen(send_buff));//接受到資料後清空傳送緩衝區 write_flag=1; read_flag=0; } } } printf("end.\n"); close(sockfd); return 0; }
/*伺服器*/ #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define BUFFER_SIZE 256 #define PORT 4568 char recv_buff[BUFFER_SIZE]; char send_buff[BUFFER_SIZE]; int main(void) { char write_flag=0; char read_flag=1; int sockfd,newsockfd;// 套結字 socklen_t addr_len; struct sockaddr_in ser_addr;//伺服器的IPv4的套結字結構 addr_len=sizeof(struct sockaddr_in); if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)//建立套結字 { perror("socket"); exit(1); } else { printf("creat socket success id:%d\n",sockfd); } bzero(&ser_addr,sizeof(struct sockaddr_in)); ser_addr.sin_family=AF_INET; ser_addr.sin_port=htons(PORT); ser_addr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(sockfd,(struct sockaddr *)(&ser_addr),sizeof(struct sockaddr))<0)//繫結 { perror("bind"); exit(2); } else { printf("bind success.\n"); } if(listen(sockfd,10)<0)//最多允許10個客戶端程序請求,監聽 { perror("listen"); exit(3); } else { printf("listening.....\n"); } memset(send_buff,0x00,sizeof(send_buff)); memset(recv_buff,0x00,sizeof(send_buff)); if((newsockfd=accept(sockfd,(struct sockaddr*)(&ser_addr),&addr_len))<0) { //accept函式使用錯誤注意複習 perror("accept"); exit(4); } else { printf("connect success.\n"); } write(newsockfd,"have connect!",strlen("have connect")); while(1) { if(strlen(send_buff)==0&&write_flag==1)//判斷髮送緩衝區是否為空 { gets(send_buff); if(write(newsockfd,send_buff,strlen(send_buff))<0) { perror("write"); exit(3); } else { printf("Client:\n"); printf(" %s\n",send_buff); } read_flag=1; write_flag=0; memset(recv_buff,0x00,strlen(recv_buff)); } else if(strlen(recv_buff)==0&&read_flag==1) { if(read(newsockfd,recv_buff,sizeof(recv_buff))<0) { perror("read"); exit(4); } else if(strlen(recv_buff)>0) { printf("Server:\n"); printf(" : %s\n",recv_buff); memset(send_buff,0x00,strlen(send_buff));//接受到資料後清空傳送緩衝區 write_flag=1; read_flag=0; } } } close(sockfd); return 0; }
效果圖: