zoukankan      html  css  js  c++  java
  • Socket网络编程--聊天程序(2)

      上一节简单如何通过Socket创建一个连接,然后进行通信。只是每个人只能说一句话。而且还是必须说完才会接收到信息,总之是很不方便的事情。所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话,主要是通过Linux下多进程fork实现的。

      一对一,server和client是每个人都可以多说几句话

      由于控制台度数据的函数fgets是阻塞函数,要每个人都可以多说话,这里我使用的是读取和发送都在不同的进程里面,使之互相没有影响。

      fork函数

      #include <unistd.h>

      pid_t fork(void);    //返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1

      client.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <errno.h>
     4 #include <string.h>
     5 #include <netdb.h> //for gethostbyname
     6 #include <sys/types.h>
     7 #include <sys/socket.h>
     8 #include <netinet/in.h>
     9 #include <arpa/inet.h>
    10 
    11 #define MAX_BUF 4096
    12 #define SERVER_PORT 12138
    13 
    14 
    15 int main(int argc,char *argv[])
    16 {
    17     int sockfd;//socket
    18     char sendBuf[MAX_BUF],recvBuf[MAX_BUF];
    19     int sendSize,recvSize;//用于记录记录发送和接收到数据的大小
    20     struct hostent * host;
    21     struct sockaddr_in servAddr;
    22     char username[32];
    23     char * p;
    24     int pid;
    25 
    26     if(argc != 3)
    27     {
    28         perror("use: ./client [hostname] [username]");
    29         exit(-1);
    30     }
    31     p=username;
    32     strcpy(p,argv[2]);
    33     printf("username:%s
    ",username);
    34     host=gethostbyname(argv[1]);
    35     if(host==NULL)
    36     {
    37         perror("fail to get host by name.");
    38         exit(-1);
    39     }
    40     printf("Success to get host by name ...
    ");
    41 
    42     //创建socket
    43     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    44     {
    45         perror("fail to establish a socket");
    46         exit(1);
    47     }
    48     printf("Success to establish a socket...
    ");
    49 
    50     /*init sockaddr_in*/
    51     servAddr.sin_family=AF_INET;
    52     servAddr.sin_port=htons(SERVER_PORT);
    53     servAddr.sin_addr=*((struct in_addr *)host->h_addr);
    54     bzero(&(servAddr.sin_zero),8);
    55 
    56     /*connect the socket*/
    57     if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)
    58     {
    59         perror("fail to connect the socket");
    60         exit(1);
    61     }
    62     printf("Success to connect the socket...
    ");
    63 
    64     //send-recv 一些返回指没有判断,具体可以看server.c
    65     if((pid=fork())<0)
    66     {
    67         perror("fork error
    ");
    68     }
    69     else if(pid>0)/*child*/
    70     {
    71         while(1)
    72         {
    73             fgets(sendBuf,MAX_BUF,stdin);
    74             send(sockfd,sendBuf,strlen(sendBuf),0);
    75             memset(sendBuf,0,sizeof(sendBuf));
    76         }
    77     }
    78     else
    79     {
    80         while(1)
    81         {
    82             recv(sockfd,recvBuf,MAX_BUF,0);
    83             printf("Server:%s
    ",recvBuf);
    84             memset(recvBuf,0,sizeof(recvBuf));
    85         }
    86     }
    87 
    88     return 0;
    89 }

      server.c

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <errno.h>
      4 #include <string.h>
      5 #include <netdb.h>
      6 #include <sys/types.h>
      7 #include <sys/socket.h>
      8 #include <sys/time.h>
      9 #include <sys/un.h>
     10 #include <sys/ioctl.h>
     11 #include <sys/wait.h>
     12 #include <netinet/in.h>
     13 #include <arpa/inet.h>
     14 
     15 
     16 #define SERVER_PORT 12138
     17 #define BACKLOG 20
     18 #define MAX_CON_NO 10
     19 #define MAX_DATA_SIZE 4096
     20 
     21 int main(int argc,char *argv[])
     22 {
     23     struct sockaddr_in serverSockaddr,clientSockaddr;
     24     char sendBuf[MAX_DATA_SIZE],recvBuf[MAX_DATA_SIZE];
     25     int sendSize,recvSize;
     26     int sockfd,clientfd;
     27     int on=1;
     28     int sinSize=0;
     29     char username[32];
     30     int pid;
     31 
     32     if(argc != 2)
     33     {
     34         printf("usage: ./server [username]
    ");
     35         exit(1);
     36     }
     37     strcpy(username,argv[1]);
     38     printf("username:%s
    ",username);
     39 
     40     /*establish a socket*/
     41     if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
     42     {
     43         perror("fail to establish a socket");
     44         exit(1);
     45     }
     46     printf("Success to establish a socket...
    ");
     47 
     48     /*init sockaddr_in*/
     49     serverSockaddr.sin_family=AF_INET;
     50     serverSockaddr.sin_port=htons(SERVER_PORT);
     51     serverSockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
     52     bzero(&(serverSockaddr.sin_zero),8);
     53 
     54     setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
     55 
     56     /*bind socket*/
     57     if(bind(sockfd,(struct sockaddr *)&serverSockaddr,sizeof(struct sockaddr))==-1)
     58     {
     59         perror("fail to bind");
     60         exit(1);
     61     }
     62     printf("Success to bind the socket...
    ");
     63 
     64     /*listen on the socket*/
     65     if(listen(sockfd,BACKLOG)==-1)
     66     {
     67         perror("fail to listen");
     68         exit(1);
     69     }
     70 
     71     /*accept a client's request*/  //这里的sinSize还没有处理,具体看下一节
     72     if((clientfd=accept(sockfd,(struct sockaddr  *)&clientSockaddr, &sinSize))==-1) 
     73     {
     74         perror("fail to accept");
     75         exit(1);
     76     }
     77     printf("Success to accpet a connection request...
    ");
     78     printf(" %s join in!
    ",inet_ntoa(clientSockaddr.sin_addr));
     79 
     80     if((pid=fork())<0)
     81     {
     82         perror("fork error
    ");
     83     }
     84     else if(pid>0)/*child*/
     85     {
     86         /*send datas to client*/
     87         while(1)
     88         {
     89             fgets(sendBuf,MAX_DATA_SIZE,stdin);
     90             if((sendSize=send(clientfd,sendBuf,strlen(sendBuf),0))!=strlen(sendBuf))
     91             {
     92                 perror("fail to send datas");
     93                 exit(1);
     94             }
     95             printf("Success to send datas
    ");
     96             memset(sendBuf,0,MAX_DATA_SIZE);
     97         }
     98     }
     99     else
    100     {
    101         while(1)
    102         {
    103             /*receive datas from client*/
    104             if((recvSize=recv(clientfd,recvBuf,MAX_DATA_SIZE,0))==-1)
    105             {
    106                 perror("fail to receive datas");
    107                 exit(1);
    108             }
    109             printf("Client:%s
    ",recvBuf);
    110             memset(recvBuf,0,MAX_DATA_SIZE);
    111         }
    112 
    113     }
    114 
    115     return 0;
    116 }

      本文地址: http://www.cnblogs.com/wunaozai/p/3870194.html

  • 相关阅读:
    weekly review 200836: the MidAutumn Festival
    weekly review 200841: Good Weekend
    解决ListView的onitemclick事件无法响应
    Android退出程序时的"再按一次退出"实现
    Android开发之文件下载
    android ExpandableListView详解
    Android ListView及其属性
    android 图片放大的处理
    android ExpandableListView
    Toast.makeText用法
  • 原文地址:https://www.cnblogs.com/wunaozai/p/3870194.html
Copyright © 2011-2022 走看看