Linux socket编程学习初步(5)--服务器多线程

来源:互联网 发布:php substr函数 中文 编辑:程序博客网 时间:2024/05/21 22:47
服务器端: 
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>#define PORT 12345#define BACKLOG 5#define MAXDATASIZE 1000void process_cli(int connfd,struct sockaddr_in client);void savedata(char* recvbuf,int len,char* cli_data);void* function(void* arg);struct ARG{ int connfd;struct sockaddr_in client;};int main(){    int listenfd,connfd;    pthread_t tid;    struct ARG *arg;    struct sockaddr_in server;    struct sockaddr_in client;    int len;    if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)    {        perror("Creating socket failed");        exit(1);    }    int opt=SO_REUSEADDR;    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));    bzero(&server,sizeof(server));    server.sin_family=AF_INET;    server.sin_port=htons(PORT);    server.sin_addr.s_addr=htonl(INADDR_ANY);    if(bind(listenfd,(struct sockaddr *)&server,sizeof(server))==-1)    {        perror("Bin() failed");        exit(1);    }    if(listen(listenfd,BACKLOG)==-1)    {        perror("listen failed");        exit(1);    }    len=sizeof(client);    while(1)    {        if((connfd=accept(listenfd,(struct sockaddr *)&client,(socklen_t*)&len))==-1)        {            perror("accept() failed");            exit(1);        }        arg=(struct ARG *)malloc(sizeof(struct ARG));        arg->connfd=connfd;        memcpy((void*)&arg->client,&client,sizeof(client));        if(pthread_create(&tid,NULL,function,(void*)arg))        {            perror("Pthread_creat() error.");            exit(1);        }    }    close(listenfd);    return 0;}void process_cli(int connfd,struct sockaddr_in client){    int num;    char recvbuf[MAXDATASIZE],sendbuf[MAXDATASIZE],cli_name[MAXDATASIZE], cli_data[MAXDATASIZE];    printf("You get a connection from %s.",inet_ntoa(client.sin_addr));    num=recv(connfd,cli_name,MAXDATASIZE,0);    if(num==0)    {        close(connfd);        printf("Clinet disconnect.");        return;    }    cli_name[num-1]='\0';    printf("Client's name is %s.\n",cli_name);    while(num=recv(connfd,recvbuf,MAXDATASIZE,0))    {        recvbuf[num]='\0';        printf("Received client( %s ) message: %s",cli_name,recvbuf);        savedata(recvbuf,num,cli_data);        int i;        for(i=0;i<num-1;i++)        {            if((recvbuf[i]>='a'&&recvbuf[i]<='z')||(recvbuf[i]>='A'&&recvbuf[i]<='Z'))            {                recvbuf[i]=recvbuf[i]+3;                if((recvbuf[i]>'Z'&&recvbuf[i]<='Z'+3)||(recvbuf[i]>'z'))                recvbuf[i]=recvbuf[i]-26;            }        sendbuf[i]=recvbuf[i];        }        sendbuf[num-1]='\0';        send(connfd,sendbuf,strlen(sendbuf),0);    }    close(connfd);    printf("Client (%s) closed connection.\n%s's data :\n%s\n",cli_name,cli_name,cli_data);}void* function(void* arg){    struct ARG *info;    info=(struct ARG *)arg;    process_cli(info->connfd,info->client);    free(arg);    pthread_exit(NULL);}void savedata(char* recvbuf,int len,char* cli_data){static int index=0;//用于表明当前数据的存储位置int i=0;while(i<len-1){        cli_data[index++]=recvbuf[i++];        cli_data[index]='\n';}index=index+1;cli_data[index]='\0';}


客户端:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#define PORT 12345#define BACKLOG 5#define MAXDATASIZE 1000#define DEST_IP "127.0.0.1"void process(FILE *fp,int sockfd);char* getMessage(char* sendline,int len,FILE* fp);int main(int argc,char *argv[]){    int sockfd;    struct hostent *he;    struct sockaddr_in server;//    if (argc!=2)//    {//        printf("Usage:%s <ip address>\n",argv[0]);//        exit(1);//    }//    if((he=gethostbyname(argv[1]))==NULL)//    {//        printf("gethostbyname () error\n");//        exit(1);//    }    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)    {        printf("sock() error\n");        exit(1);    }    bzero(&server,sizeof(server));    server.sin_family=AF_INET;    server.sin_port=htons(PORT);//    server.sin_addr=*((struct in_addr *)he->h_addr);    if(inet_aton(DEST_IP,&server.sin_addr)==0)    {        fprintf(stderr,"Inet_aton erro\n");        exit(1);    }  //by fupeng    if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1)    {        printf("connect() failed\n");        exit(1);    }    process(stdin,sockfd);    close(sockfd);}void process(FILE *fp,int sockfd){    char sendline[MAXDATASIZE],recvline[MAXDATASIZE];    int num;    printf("connected to server.\n");    printf("Input client's name:");    if(fgets(sendline,MAXDATASIZE,fp)==NULL)    {        printf("\nExit.\n");        return;    }    send(sockfd,sendline,strlen(sendline),0);    while(getMessage(sendline,MAXDATASIZE,fp)!=NULL)    {        send(sockfd,sendline,strlen(sendline),0);        if((num=recv(sockfd,recvline,MAXDATASIZE,0))==0)        {            printf("\nServer terminated.\n");            return;        }        recvline[num]='\0';        printf("Server Message:%s\n",recvline);    }printf("\nExit\n");}char *getMessage(char* sendline,int len,FILE* fp){    printf("Input string to server:");    return(fgets(sendline,MAXDATASIZE,fp));}

 

这里读者因该了解线程创建的一些函数及其使用,其中服务器端源代中的void savedata(char* recvbuf,int len,char* cli_data)函数用于保存客户端发送的信息。当客户端结束后能把客户端发送过的信息显示出来。(当然它可以用于在服务器上保存用户通信记录,但需要完善改进。)