實現的功能是可以socket服務器允許多個客戶端連接,連接到服務器的時候能夠打印出連接的IP地址和端口,服務端連接到數據能夠將客戶端的IP地址和發送內容打印出來。
效果:
服務端
appledeMacBook-Pro:聊天室 apple$ ./a.out 8888
有一個遠程機器連接到本機,ip地址:127.0.0.1,端口:40927
分配句柄成功
從客戶端:127.0.0.1獲取到數據vvv
從客戶端:127.0.0.1獲取到數據0f
從客戶端:127.0.0.1獲取到數據.test data
客戶端
appledeMacBook-Pro:c++Primer apple$ telnet 127.0.0.1 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
恭喜你成功連接到本服務器
vvv
vvv
0f
.0f
test data
.test data
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <pthread.h> struct ClientInfo{ int newsockfd; char* Ip; }clientInfo; void* connection_handler(void *); void error(const char *msg) { perror(msg); exit(1); } //因為是直接通過telent測試在發送的時候會帶一個\n不能直接通過strcmp來比,所以寫了下面的程序來處理 int isExit(char *s1) { if(strlen(s1)<6) { return 0; } char const *str="quit"; while(*str!='\0') { if(*str-*s1==0) { } else { printf("不同的是:%c,%c\n",*str,*s1); return 0; } str++,s1++; } return 1; } int main(int argc, char const* argv[]) { pthread_t thread_id; int sockfd,newsockfd,portno; socklen_t client; struct sockaddr_in serv_addr,cli_addr; int n; if(argc<2){ fprintf(stderr,"請啟動程序的時候輸入一個正確的端口號"); exit(1); } sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd<0) { error("打開Socket錯誤"); } bzero((char *)&serv_addr,sizeof(serv_addr)); portno=atoi(argv[1]); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=INADDR_ANY; serv_addr.sin_port=htons(portno); if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) { error("綁定端口錯誤"); } listen(sockfd,5); client=sizeof(cli_addr); while((newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&client))) { printf("有一個遠程機器連接到本機,ip地址:%s,端口:%d\n",inet_ntoa(cli_addr.sin_addr),cli_addr.sin_port); clientInfo.newsockfd=newsockfd; clientInfo.Ip=inet_ntoa(cli_addr.sin_addr); if( pthread_create( &thread_id , NULL , connection_handler , (void*) &clientInfo) < 0) { perror("創建線程失敗"); return 1; } puts("分配句柄成功"); } if(newsockfd<0) { error("接受客戶端請求失敗"); } close(newsockfd); close(sockfd); return 0; } void *connection_handler(void* arg) { ClientInfo *Client; Client=(struct ClientInfo*) arg; int sock=Client->newsockfd; char* c=Client->Ip; int read_size; char buffer[256]; char *message , client_message[2000]; //改善一個歡迎信息到客戶端 message = "恭喜你成功連接到本服務器\n"; write(sock , message , strlen(message)); while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 ) { client_message[read_size]='\0'; printf("從客戶端:%s獲取到數據%s",c,client_message); write(sock,client_message,strlen(client_message)); memset(client_message,0,2000); } if(read_size==0) { puts("客戶端關閉"); } else if(read_size==-1) { perror("接收數據錯誤"); } }