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\n",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 ...\n");
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...\n");
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...\n");
63 
64     //send-recv 一些返回指沒有判斷,具體可以看server.c
65     if((pid=fork())<0)
66     {
67         perror("fork error\n");
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\n",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]\n");
 35         exit(1);
 36     }
 37     strcpy(username,argv[1]);
 38     printf("username:%s\n",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...\n");
 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...\n");
 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...\n");
 78     printf(" %s join in!\n",inet_ntoa(clientSockaddr.sin_addr));
 79 
 80     if((pid=fork())<0)
 81     {
 82         perror("fork error\n");
 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\n");
 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\n",recvBuf);
110             memset(recvBuf,0,MAX_DATA_SIZE);
111         }
112 
113     }
114 
115     return 0;
116 }

 

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM