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

posted @ 2014-07-26 16:52  无脑仔的小明  阅读(3749)  评论(2编辑  收藏  举报