由于单进程服务器只能处理一个客户端,所以引入了多线程,这样便可以处理多客户端,同时还可以锻炼多线程的一些知识,并加以巩固网络编程。
在这里我使用的环境是Linux,windows的不能运行这个程序。
//config.h
#ifndef HEADER_H #define HEADER_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #include <arpa/inet.h> #include <pthread.h> #include <ctype.h> #define SERVER_IP "127.0.0.1" #define CLIENT_IP "127.0.0.1" #define SERVER_PORT 8887 #endif // HEADER_H
#include "config.h" //client information struct clientInfo{ int socke; sockaddr_in sockClient; }; void *delClient(void *arg){ char buf[1024]; clientInfo *client = (clientInfo*)arg; printf("new client has connect: ip:%s,port:%d ",inet_ntoa(client->sockClient.sin_addr),htons(client->sockClient.sin_port)); while(1){ int n = read(client->socke,buf,1024); if(n == 0 || n < 0) { printf("client %s has error and exit! ",inet_ntoa(client->sockClient.sin_addr)); return NULL; } for(size_t i = 0; i < strlen(buf)+1;i++){ buf[i] = toupper(buf[i]); } write(client->socke,buf,n); } } int main(){ //init socket int sockSer, sockClient, i = 0; sockaddr_in addrSer,addrCli; clientInfo clientinfo[CLIENT_NUM]; if((sockSer = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("socket error:"); return -1; } //init addrser inet_pton(AF_INET,SERVER_IP,&addrSer.sin_addr.s_addr); addrSer.sin_family = AF_INET; addrSer.sin_port = htons(SERVER_PORT); //bind if(0 != bind(sockSer,(sockaddr*)&addrSer,sizeof(addrSer))){ perror("bind error:"); return -1; } //listen if(0 != listen(sockSer,CLIENT_NUM)){ perror("listen error:"); return 0; } //acctept while (1) { int len = sizeof(addrCli); sockClient = accept(sockSer,(sockaddr*)&addrCli,(socklen_t*)&len); if(sockClient == -1){ perror("accept error!"); break; } //init client msg to thread memcpy(&clientinfo[i].sockClient,&addrCli,sizeof(addrCli)); clientinfo[i].socke = sockClient; //create thread pthread_t pid; pthread_create(&pid,NULL,delClient,(void*)&clientinfo[i]); pthread_detach(pid); } return 0; }
客户端,可以使用nc命令来链接服务器,例如:
//nc 服务器ip地址 服务器端口号 nc 127.0.0.1 8887
也可以使用自己写的:
//client.c #include "config.h" int main() { int sockSer; sockaddr_in addrSer; sockSer = socket(AF_INET,SOCK_STREAM,0); if(sockSer == -1){ perror("socket init error: "); return -1; } addrSer.sin_family = AF_INET; addrSer.sin_port = htons(SERVER_PORT); inet_pton(AF_INET,CLIENT_IP,&addrSer.sin_addr.s_addr); if( 0 != connect(sockSer,(sockaddr*)&addrSer,sizeof(sockaddr))) { perror("connect error:"); return -1; } char buf[100]; while(1){ scanf("%s",buf); write(sockSer,buf,100); read(sockSer,buf,100); printf("server send back: %s",buf); } }