socket Server and Client 多进程 互相通信 实测OK

server

可收可发,使用多进程
使用方法
$ sudo gcc server.c -o server
$ ./server

#include
#include
#include //数据类型定义
#include
#include //定义数据结构sockaddr_in
#include //提供socket函数及数据结构
#include
#include
#include
#include
#include
#include
#include
#define PERM S_IRUSR|S_IWUSR
#define MYPORT 1680 //宏定义定义通信端口
#define BACKLOG 10 //宏定义,定义服务程序可以连接的最大客户数量
#define WELCOME "|----------Welcome to the chat room! ----------|" //宏定义,当客户端连接服务端时,想客户发送此欢迎字符串
//转换函数,将int类型转换成char *类型
void itoa(int i,char*string)
    {
    int power,j;
    j=i;
    for(power=1;j>=10;j/=10)
    power*=10;
    for(;power>0;power/=10)
    {
    *string++='0'+i/power;
    i%=power;
    }
    *string='\0';
    }

//得到当前系统时间
void get_cur_time(char * time_str)
    {
    time_t timep;
    struct tm *p_curtime;
    char *time_tmp;
    time_tmp=(char *)malloc(2);
    memset(time_tmp,0,2);

    memset(time_str,0,20);
    time(&timep);
    p_curtime = localtime(&timep);
    strcat(time_str," (");
    itoa(p_curtime->tm_hour,time_tmp);
    strcat(time_str,time_tmp);
    strcat(time_str,":");
    itoa(p_curtime->tm_min,time_tmp);
    strcat(time_str,time_tmp);
    strcat(time_str,":");
    itoa(p_curtime->tm_sec,time_tmp);
    strcat(time_str,time_tmp);
    strcat(time_str,")");
    free(time_tmp);
    }
//创建共享存储区,进程间通讯
key_t shm_create()
{
    key_t shmid;
    //shmid = shmget(IPC_PRIVATE,1024,PERM);
    if((shmid = shmget(IPC_PRIVATE,1024,PERM)) == -1) // 创建共享内存, 共享内存就是允许两个不相关的进程访问同一个逻辑内存, 返回值:系统生成一个相应的共享内存标识符
    {
        fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));
        exit(1);
    }
    return shmid;
}
    
//端口绑定函数,创建套接字,并绑定到指定端口
int bindPort(unsigned short int port)
{
    int sockfd;
    int ret, on;
    struct sockaddr_in my_addr;
    sockfd = socket(AF_INET,SOCK_STREAM,0);//创建基于流套接字

    on = 1;
    ret = setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); ///解决Ctr+C带来的端口问题
    
    my_addr.sin_family = AF_INET;//IPv4协议族
    my_addr.sin_port = htons(port);//端口转换
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero),0);//置空

    if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1)//绑定本地IP
    {
        perror("bind");
        exit(1);
    }
    printf("bing success!\n");
    return sockfd;
}
    
int main(int argc, char *argv[])
{
    int sockfd,clientfd,sin_size,recvbytes; //定义监听套接字、客户套接字
    pid_t pid,ppid; //定义父子线程标记变量
    char *buf, *r_addr, *w_addr, *temp, *time_str;//="\0"; //定义临时存储区
    struct sockaddr_in their_addr; //定义地址结构
    key_t shmid;

    shmid = shm_create(); //创建共享存储区

    temp = (char *)malloc(255);
    time_str=(char *)malloc(20);
    sockfd = bindPort(MYPORT);//绑定端口
    while(1)
    {
        if(listen(sockfd,BACKLOG) == -1)//在指定端口上监听
        {
            perror("listen");
            exit(1);
        }
        printf("listening......\n");
        if((clientfd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1)//接收客户端连接
        {
            perror("accept");
            exit(1);
        }
        printf("accept from:%d\n",inet_ntoa(their_addr.sin_addr));
        send(clientfd,WELCOME,strlen(WELCOME),0);//发送问候信息
        buf = (char *)malloc(255);

        ppid = fork();//创建子进程
        if(ppid == 0)
        {
            //printf("ppid=0\n");
            pid = fork(); //创建子进程
            while(1)
            {
                if(pid > 0)
                {
                    //printf(" this is pid > 0\n\r");
                    //父进程用于接收信息
                    memset(buf,0,255);
                    //printf("recv\n");
                    //sleep(1);
                    if((recvbytes = recv(clientfd,buf,255,0)) <= 0)
                    {
                        perror("recv1");
                        close(clientfd);
                        raise(SIGKILL);
                        exit(1);
                    }
                    //write buf's data to share memory
                    w_addr = shmat(shmid, 0, 0);
                    memset(w_addr, '\0', 1024);
                    strncpy(w_addr, buf, 1024);
                    get_cur_time(time_str);
                    strcat(buf,time_str);
                    printf(" %s\n",buf);
                }
                else if(pid == 0)
                {
                    //printf(" this is pid = 0\n\r");
                    //子进程用于发送信息
                    //scanf("%s",buf);
                    //sleep(1);
                    //r_addr = shmat(shmid, 0, 0); 调用成功时返回一个指向共享内存第一个字节的指针

                    fgets(temp,1024,stdin);
                    get_cur_time(time_str);
                    strcat(temp,time_str);
                    if((send(clientfd,temp,strlen(temp),0)) < 0)
                    {
                        printf("send mes error: %s errno : %d",strerror(errno),errno);
                        exit(0);
                    }
                }
                else
                    perror("fork");
                }
            }
        }
    printf("------------------------------\n");
    free(buf);
    close(sockfd);
    close(clientfd);
    return 0;
}


client

可收可发,使用多进程
使用方法:
sudo gcc client.c -o client
./client 127.0.0.1 1680 userName

#include
#include //定义数据结构sockaddr_in
#include //提供socket函数及数据结构
#include //数据类型定义
#include
#include
#include
#include
#include
#include
 int main(int argc, char *argv[])
 {
     struct sockaddr_in clientaddr;//定义地址结构
     pid_t pid;
     int clientfd,sendbytes,recvbytes;//定义客户端套接字
     struct hostent *host;
     char *buf,*buf_r;
     if(argc < 4)
     {
         printf("usage:\n");
         printf("%s host port name\n",argv[0]);
         exit(1);
     }
     host = gethostbyname(argv[1]);
     if((clientfd = socket(AF_INET,SOCK_STREAM,0)) == -1) //创建客户端套接字
     {
         perror("socket\n");
         exit(1);
     }
     //绑定客户端套接字
     clientaddr.sin_family = AF_INET;
     clientaddr.sin_port = htons((uint16_t)atoi(argv[2]));
     clientaddr.sin_addr = *((struct in_addr *)host->h_addr);
     bzero(&(clientaddr.sin_zero),0);
     if(connect(clientfd,(struct sockaddr *)&clientaddr,sizeof(struct sockaddr)) == -1) //连接服务端
     {
         perror("connect\n");
         exit(1);
     }
     buf=(char *)malloc(120);
     memset(buf,0,120);
     buf_r=(char *)malloc(100);
     
     if( recv(clientfd,buf,100,0) == -1)
     {
         perror("recv:");
         exit(1);
     }
     printf("\n%s\n",buf);
     
     pid = fork();//创建子进程
     while(1)
     {
         if(pid > 0){
             //父进程用于发送信息
             
             //get_cur_time(time_str);
             
             strcpy(buf,argv[3]);
             strcat(buf,":");
             memset(buf_r,0,100);
             //gets(buf_r);
             fgets(buf_r,100,stdin);
             strncat(buf,buf_r,strlen(buf_r)-1);
             //strcat(buf,time_str);
             //printf("---%s\n",buf);
             if((sendbytes = send(clientfd,buf,strlen(buf),0)) == -1)
             {
                 perror("send\n");
                 exit(1);
             }
         }
         else if(pid == 0)
         {
             //子进程用于接收信息
             memset(buf,0,100);
             if(recv(clientfd,buf,100,0) <= 0)
             {
                 perror("recv:");
                 close(clientfd);
                 raise(SIGSTOP);
                 exit(1);
             }
             printf("%s\n",buf);
         }
         else
             perror("fork");
         }
     close(clientfd);
     return 0;
 }

运行效果图

其他学习用的代码,请忽略

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
server, 仅打印收到的数据

#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
 #define MAXLINE 1024
 int main(int argc,char **argv)
{
     int listenfd,connfd;
     struct sockaddr_in sockaddr;
     char buff[MAXLINE];
     int n;
     
     memset(&sockaddr,0,sizeof(sockaddr));
     
     sockaddr.sin_family = AF_INET;
     sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
     sockaddr.sin_port = htons(10004);
     
     listenfd = socket(AF_INET,SOCK_STREAM,0);
     
     bind(listenfd,(struct sockaddr *) &sockaddr,sizeof(sockaddr));
     
     listen(listenfd,1024);


    #if 1
     for(;;)
     {
         if((connfd = accept(listenfd,(struct sockaddr*)NULL,NULL))==-1)
         {
             printf("accpet socket error: %s errno :%d\n",strerror(errno),errno);
             continue;
         }
         break;
     }
     #endif
     
     printf("Please wait for the client information\n");
     
     for(;;)
     {
        #if 0
         if((connfd = accept(listenfd,(struct sockaddr*)NULL,NULL))==-1)
         {
             printf("accpet socket error: %s errno :%d\n",strerror(errno),errno);
             continue;
         }
         #endif
         sleep(1);
         n = recv(connfd,buff,MAXLINE,0);
         if(n>0){
             buff[n] = '\0';
             printf("recv msg from client:%s",buff);
             //close(connfd);
         }
     }
     close(listenfd);
 }
 

client 发送输入的数据到server

#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #define MAXLINE 1024
 int main(int argc,char **argv)
 {
     char *servInetAddr = "127.0.0.1";
     int socketfd;
     struct sockaddr_in sockaddr;
     char recvline[MAXLINE], sendline[MAXLINE];
     int n;
     
     if(argc != 2)
     {
         //printf("client  \n");
         //exit(0);
     }
     
     socketfd = socket(AF_INET,SOCK_STREAM,0);
     memset(&sockaddr,0,sizeof(sockaddr));
     sockaddr.sin_family = AF_INET;
     sockaddr.sin_port = htons(10004);
     inet_pton(AF_INET,servInetAddr,&sockaddr.sin_addr);
     if((connect(socketfd,(struct sockaddr*)&sockaddr,sizeof(sockaddr))) < 0 )
     {
         printf("connect error %s errno: %d\n",strerror(errno),errno);
         exit(0);
     }

     

    while(1){

        printf("send message to server\n");
         fgets(sendline,1024,stdin);

         if((send(socketfd,sendline,strlen(sendline),0)) < 0)
         {
             printf("send mes error: %s errno : %d",strerror(errno),errno);
             exit(0);
         }
        
     }
     
     close(socketfd);
     printf("exit\n");
     exit(0);
}

你可能感兴趣的:(Linux)