周末無聊,建立個多線程實現簡單聊天功能,順便溫習下linux的TCP/IP。
下面貼代碼大家一起學習!有些代碼跟(1)篇重複,我就不注釋了!
========tcp_server.c============
#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <pthread.h>#define PORT 3333void *thrd_write(void *arg) //寫線程{ int sockfd=(int)arg; //穿進來的用戶端連接埠 char buf[100]; while(1) { fgets(buf,100,stdin); //從螢幕得到你輸入的字元 if(write(sockfd,buf,sizeof(buf))<0) //寫功能 { fprintf(stderr,"write Error:%s\a\n",strerror(errno)); exit(1); } } pthread_exit(NULL); //線程退出}int main(int argc, char *argv[]){ int sockfd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; char buf[100]; sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd == -1) { fprintf(stderr,"Socket error:%s\n",strerror(errno)); exit(1); } bzero(&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); int on=1; setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //上次(1)篇沒解釋,其實這個就是阻止服務端一關掉,再啟動,運行不了的情況發生 if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr_in))==-1) { fprintf(stderr,"Bind error:%s\n",strerror(errno)); exit(1); } if(listen(sockfd,20)==-1) { fprintf(stderr,"listen error:%s\n",strerror(errno)); exit(1); } int new_fd,res2; pid_t child; int r_size; pthread_t thread_write; //線程id,即線程標識符 while(1) { printf("wait!!!!!\n"); memset(buf,0,100); sin_size = sizeof(struct sockaddr_in); if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) { fprintf(stderr,"Accept error:%s\n",strerror(errno)); exit(1); } else { fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); res2=pthread_create(&thread_write,NULL,thrd_write,new_fd); //建立線程 if(res2!=0) { perror("Pthread2 create fail"); exit(res2); } while(1) //讀取用戶端資訊 { char buf[100]; int r_size; if((r_size=read(new_fd,buf,100))==-1) { fprintf(stderr,"Read error:%s\n",strerror(errno)); exit(1); } printf("Server Received%d::%s\n",r_size,buf); } } } close(sockfd); exit(0);}
==========tcp_client.c===============
#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <pthread.h>#define PORT 3333void *thrd_write(void *arg) //同樣建立個寫線程{ int sockfd=(int)arg; char buf[100]; while(1) { fgets(buf,100,stdin); if(write(sockfd,buf,sizeof(buf))<0) { fprintf(stderr,"write Error:%s\a\n",strerror(errno)); exit(1); } } pthread_exit(NULL);}int main(int argc, char *argv[]){ int sockfd; char buf[100]; struct sockaddr_in server_addr; struct hostent *host; sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) { fprintf(stderr,"Socket error:%s\n",strerror(errno)); exit(1); } bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(PORT); server_addr.sin_addr.s_addr=inet_addr("192.168.1.155"); int con_flag,res2; pthread_t thread_write; con_flag=connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)); //串連服務端 if(con_flag==-1) { fprintf(stderr,"Connect Error:%s\a\n",strerror(errno)); exit(1); } else { res2=pthread_create(&thread_write,NULL,thrd_write,sockfd); if(res2!=0) { perror("Pthread2 create fail"); exit(res2); } while(1) //讀服務端資訊 { char buf[100]; int r_size; if((r_size=read(sockfd,buf,100))==-1) { fprintf(stderr,"Read error:%s\n",strerror(errno)); exit(1); } printf("Client Received%d::%s\n",r_size,buf); } } void *thrd_ret1; pthread_join(thread_read,&thrd_ret1); //線程阻塞等待結束 close(sockfd); return 0;}
程式運行結果如下:
root@wyz-vlinux:~/test# ./tcp_server
wait!!!!!
Server get connection from 192.168.1.155
Server Received100::hello server
hello client
Server Received100::nice to meet you!
Nice to meet you,too!
root@wyz-vlinux:~/test# ./tcp_client
hello server
Client Received100::hello client
nice to meet you!
Client Received100::Nice to meet you,too!