(OK) server-client-pthread-c language
                                            
server.c
client.c
                                    
点击(此处)折叠或打开
- // gcc
-lpthread server.c
-o server
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <pthread.h>
- //#endif
- #define BUF_SIZE 1024        //默认缓冲区
- #define SERVER_PORT 11111    //监听端口
- #define SERVER_HOST "127.0.0.1"    //服务器IP地址
- #define EPOLL_RUN_TIMEOUT -1    //epoll的超时时间
- #define EPOLL_SIZE 10000    //epoll监听的客户端的最大数目
- #define LISTEN_SIZE 10        //监听队列长度
- #define STR_WELCOME "Welcome to seChat! You ID is : Client #%d"
- #define STR_MESSAGE "Client #%d>> %s"
- #define STR_NOONE_CONNECTED "Noone connected to server expect you!"
- #define CMD_EXIT "EXIT"
- //两个有用的宏定义:检查和赋值并且检测
- #define CHK(eval)
if(eval 
< 0){perror("eval");
exit(-1);}
- #define CHK2(res, eval)
if((res
= eval) 
< 0){perror("eval");
exit(-1);}
- void* handle_message(void
*arg);
- int main(int argc, char
*argv[])
- {
-     int listener;        //监听socket
-     struct sockaddr_in addr, peer;
-     addr.sin_family 
= PF_INET;
-     addr.sin_port 
= htons(SERVER_PORT);
-     addr.sin_addr.s_addr
= inet_addr(SERVER_HOST);
-     socklen_t socklen;
-     socklen = sizeof(struct sockaddr_in);
-     int client;
-     CHK2(listener, socket(PF_INET, SOCK_STREAM, 0));    //初始化监听socket
-     // 设置套接字选项避免地址使用错误
-     int on=1;
-     if((setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
-     { 
-         perror("setsockopt failed");
-         exit(EXIT_FAILURE);
-     } 
-     CHK(bind(listener,
(struct sockaddr *)&addr, sizeof(addr)));    //绑定监听socket
-     //printf("listen\n");
-     CHK(listen(listener, LISTEN_SIZE));    //设置监听
-     printf("listening\n");
-     while (1)
{
-         //printf("accept\n");
-         CHK2(client, accept(listener,
(struct sockaddr *)&peer,
&socklen));
-         printf("accepted\n");
-         pthread_t reader;
-         int rt 
= pthread_create(&reader,
NULL, handle_message,
(void *)&client);
-         if (-1
== rt)
{
-             printf("thread creation error\n");
-             return -1;
-         }
-     }
- }
- void* handle_message(void
*arg)
- {
-     int client 
= *((int*)arg);
-     //sleep(5);
-     char buf[BUF_SIZE];
-     int len;
-     while(1){
-         bzero(buf, BUF_SIZE);
-         CHK2(len, recv(client, buf, BUF_SIZE,
 0));    //接受客户端信息
-         if (len
== 0)        //客户端关闭或出错,关闭socket,并从list移除socket
-         {
-             printf("close-client: %d\n", client);
-             CHK(close(client));
-             return NULL;
-         } else            //向客户端发送信息
-         {
-             CHK(send(client, STR_NOONE_CONNECTED, strlen(STR_NOONE_CONNECTED),
 0));
-             printf("receive: %s from %d\n", buf, client);
-         }
-     }
-     //return
len;
-     //return
NULL;
- }
点击(此处)折叠或打开
- // gcc client.c
-o client
- // gcc 
-lpthread client.c 
-o client
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <sys/epoll.h>
- //#endif
- #define BUF_SIZE 1024        //默认缓冲区
- #define SERVER_PORT 11111    //监听端口
- #define SERVER_HOST "127.0.0.1"    //服务器IP地址
- #define EPOLL_RUN_TIMEOUT -1    //epoll的超时时间
- #define EPOLL_SIZE 10000    //epoll监听的客户端的最大数目
- #define STR_WELCOME "Welcome to seChat! You ID is : Client #%d"
- #define STR_MESSAGE "Client #%d>> %s"
- #define STR_NOONE_CONNECTED "Noone connected to server expect you!"
- #define CMD_EXIT "EXIT"
- //两个有用的宏定义:检查和赋值并且检测
- #define CHK(eval)
if(eval 
< 0){perror("eval");
exit(-1);}
- #define CHK2(res, eval)
if((res
= eval) 
< 0){perror("eval");
exit(-1);}
- char message[BUF_SIZE];
- /*
-     流程:
-         调用fork产生两个进程,两个进程通过管道进行通信
-         子进程:等待客户输入,并将客户输入的信息通过管道写给父进程
-         父进程:接受服务器的信息并显示,将从子进程接受到的信息发送给服务器
- */
- int main(int argc, char
*argv[])
- {
-     int sock, pid, pipe_fd[2], epfd;
-     struct sockaddr_in addr;
-     addr.sin_family 
= PF_INET;
-     addr.sin_port 
= htons(SERVER_PORT);
-     addr.sin_addr.s_addr
= inet_addr(SERVER_HOST);
-     static struct epoll_event ev, events[2];
-     ev.events 
= EPOLLIN | EPOLLET;
-     //退出标志
-     int continue_to_work 
= 1;
-     CHK2(sock, socket(PF_INET, SOCK_STREAM, 0));
-     CHK(connect(sock,
(struct sockaddr *)&addr, sizeof(addr))
< 0);
-     CHK(pipe(pipe_fd));
-     CHK2(epfd, epoll_create(EPOLL_SIZE));
-     ev.data.fd
= sock;
-     CHK(epoll_ctl(epfd, EPOLL_CTL_ADD, sock,
&ev));
-     ev.data.fd
= pipe_fd[0];
-     CHK(epoll_ctl(epfd, EPOLL_CTL_ADD, pipe_fd[0],
&ev));
-     // 调用fork产生两个进程
-     CHK2(pid, fork());
-     switch (pid)
{
-     case 0:        // 子进程
-         close(pipe_fd[0]);    //
 关闭读端
-         printf("Enter 'exit' to exit\n");
-         while 
(continue_to_work) 
{
-             bzero(&message, BUF_SIZE);
-             fgets(message, BUF_SIZE, stdin);
-             // 当收到exit命令时,退出
-             if 
(strncasecmp(message, CMD_EXIT, strlen(CMD_EXIT))
== 0)
{
-                 continue_to_work = 0;
-             } 
else {
-                 CHK(write(pipe_fd[1], message,
 strlen(message)
- 1));
-             }
-         }
-         break;
-     default:        // 父进程
-         close(pipe_fd[1]);    //
 关闭写端
-         int epoll_events_count, res;
-         while 
(continue_to_work) 
{
-             CHK2(epoll_events_count, epoll_wait(epfd, events, 2,
 EPOLL_RUN_TIMEOUT));
-             for 
(int i = 0; i
< epoll_events_count; i++)
{
-                 bzero(&message, BUF_SIZE);
-                 if 
(events[i].data.fd
== sock)    //从服务器接受信息
-                 {
-                     CHK2(res, recv(sock, message, BUF_SIZE,
 0));
-                     if 
(res == 0)    //服务器已关闭
-                     {
-                         CHK(close(sock));
-                         continue_to_work = 0;
-                     } 
else {
-                         printf("%s\n", message);
-                     }
-                 } 
else    //从子进程接受信息
-                 {
-                     CHK2(res, read(events[i].data.fd,
 message, BUF_SIZE));
-                     if 
(res == 0)
{
-                         continue_to_work = 0;
-                     } 
else {
-                         CHK(send(sock, message, BUF_SIZE, 0));
-                     }
-                 }
-             }
-         }
-     }
-     if (pid)
{
-         close(pipe_fd[0]);
-         close(sock);
-     } else
{
-         close(pipe_fd[1]);
-     }
-     return 0;
- }
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号