0
点赞
收藏
分享

微信扫一扫

JavaWeb——IDEA相关配置(Tomcat安装)

悲催博士僧 2023-10-22 阅读 41

 

服务器端:server.c 

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <arpa/inet.h>
  6 #include <pthread.h>
  7 void* working(void *arg);
  8 //信息结构体
  9 struct sockinfo
 10 {
 11     struct sockaddr_in addr;//用来存储地址信息
 12     int fd;//用来存储文件描述符
 13 };
 14 //创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表
 15 //在C++中可以维护一个STL
 16 struct sockinfo infos[512];
 17 int main()
 18 {
 19     //创建监听的套接字
 20     int lfd=socket(AF_INET,SOCK_STREAM,0);
 21     if(lfd==-1)
 22     {
 23         perror("socket");
 24         return -1;
 25     }
 26     struct sockaddr_in addr;
 27     addr.sin_family=AF_INET;
 28     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序
 29     addr.sin_addr.s_addr=INADDR_ANY;
 30     int ret=bind(lfd,(struct sockaddr*)&addr,sizeof(addr));
 31     if(ret==-1)
 32     {
 33         perror("bind");
 34         return -1;
 35     }
 36     //设置监听
 37     ret=listen(lfd,128);//设置最大监听数量为128个
 38     if(ret==-1)
 39     {
 40         perror("listen");
 41         return -1;
 42     }
 43
 44     //初始化结构数组
 45     int max=sizeof(infos)/sizeof(infos[0]);//计算数组的大小
 46     //将结构体数组中每个元素初始化为0
 47     int i=0;
 48     for(i=0;i<max;++i)
 49     {
 50         bzero(&infos[i],sizeof(infos[i]));
 51         //memset(infos,0,sizeof(infos));
 52         //将结构体中的文件描述符修改为-1
 53         infos[i].fd=-1;//通过文件描述符的值是否为-1来判断当前数组元素是否是被占用的
 54
 55     }
 56
 57     //阻塞并等待客户端的连接
 58     int clilen=sizeof(struct sockaddr_in);
 59     while(1)
 60     {
 61         struct sockinfo* pinfo;
 62         int i=0;
 63         for(i=0;i<max;++i)
 64         {
 65             if(infos[i].fd==-1)//此时说明该元素是可以使用的
 66             {
 67                 pinfo=&infos[i];
 68                 break;
 69             }
 70         }
 71         int cfd=accept(lfd, (struct sockaddr*)&pinfo->addr,&clilen);
 72         pinfo->fd=cfd;//保存返回的文件描述符
 73         if(cfd==-1)
 74         {
 75             perror("accept");
 76             break;
 77         }
 78         //与客户端建立连接后,需要与客户端进行通信。与客户端的通信需要一个子线程来连接
 79         //创建子线程
 80         pthread_t tid;
 81         pthread_create(&tid,NULL,working,pinfo);//pinfo就是需要传递给working函数的参数
 82         //任务执行完毕之后,子线程需要退出。此时,需要由主线程来释放子线程的资源
 83         //此时,需要调用detach()函数来使主线程与子线程进行资源分离
 84         pthread_detach(tid);
 85     }
 86     close(lfd);
 87     return 0;
 88 }
 89
 90 //子线程的任务函数·
 91 void* working(void *arg)
 92 {
 93     struct sockinfo* pinfo=(struct sockinfo*)arg;
 94     //打印客户端地址
 95     char ip[1024]={0};
 96     printf("客户端IP地址:%s,端口:%d\n",inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(pinfo->addr.sin_port));
 97     //和客户建立通信
 98     while(1)
 99     {
100         char buf[1024];
101         memset(buf,0,sizeof(buf));
102         int len=read(pinfo->fd,buf,sizeof(buf));
103         if(len>0)
104         {
105             printf("客户端say:%s\n",buf);
106             write(pinfo->fd,buf,len);
107         }
108         else if(len==0)
109         {
110             printf("客户端断开了连接...\n");
111             break;
112         }
113         else
114         {
115             perror("read");
116             break;
117         }
118     }
119     close(pinfo->fd);
120     pinfo->fd=-1;//将通信描述符再次初始化为-1
121     return NULL;
122 }

客户端:client.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <arpa/inet.h>
  6 int main()
  7 {
  8     //创建监听的套接字
  9     int fd=socket(AF_INET,SOCK_STREAM,0);
 10     if(fd==-1)
 11     {
 12         perror("socket");
 13         exit(0);
 14     }
 15     struct sockaddr_in addr;
 16     addr.sin_family=AF_INET;
 17     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序
 18     inet_pton(AF_INET,"192.168.64.134",&addr.sin_addr.s_addr);
 19     int ret=connect(fd,(struct sockaddr*)&addr,sizeof(addr));
 20     if(ret==-1)
 21     {
 22         perror("connetc");
 23         exit(0);
 24     }
 25     //和服务器通信
 26     int number=0;
 27     while(1)
 28     {   //发送数据
 29         char buf[1024];
 30         sprintf(buf,"你好,服务器...%d\n",number++);
 31         write(fd,buf,strlen(buf)+1);
 32         //接收数据
 33         memset(buf,0,sizeof(buf));
 34         int len=read(fd,buf,sizeof(buf));
 35         if(len>0)
 36         {
 37             printf("服务器say:%s\n",buf);
 38             write(fd,buf,len);
 39         }
 40         else if(len==0)
 41         {
 42             printf("服务器断开了连接...\n");
 43             break;
 44         }
 45         else
 46         {
 47             perror("read");
 48             break;
 49         }
 50         sleep(1);
 51     }
 52     close(fd);
 53     return 0;
 54 }

编译:gcc server.c -lpthread -o server

           gcc client.c -lpthread -o client

启动运行:

                先运行服务器端./server,再运行客户端./client

基于线程池的并发性socket通信(服务器端源码)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "threadpool.h"

void working(void *arg);
void acceptconn(void *arg);
//信息结构体
struct sockinfo
{
        struct sockaddr_in addr;//用来存储地址信息
        int fd;//用来存储文件描述符
};
//任务结构体
typedef struct poolinfo
{
        threadpool *p;
        int fd;
}poolinfo;
//创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表
//在C++中可以维护一个STL
struct sockinfo infos[512];
int main()
{
        //创建监听的套接字
        int lfd=socket(AF_INET,SOCK_STREAM,0);
        if(lfd==-1)
        {
                perror("socket");
                return -1;
        }
        struct sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序
        addr.sin_addr.s_addr=INADDR_ANY;
        int ret=bind(lfd,(struct sockaddr*)&addr,sizeof(addr));
        if(ret==-1)
        {
                perror("bind");
                return -1;
        }
        //设置监听
        ret=listen(lfd,128);//设置最大监听数量为128个
        if(ret==-1)
        {
                perror("listen");
                return -1;
        }
        //创建线程池
        threadpool *pool=threadPoolCreate(3,8,100);
        poolinfo *info=(poolinfo*)malloc(sizeof(poolinfo));
        info->p=pool;
        info->fd=fd;
        //将任务函数添加到线程池中
        threadpoolAdd(pool,acceptconn,info);
        //主线程任务完成之后自动退出
        pthread_exit(NULL);
        return 0;
}
void acceptconn(void *arg)
{
        poolinfo* poolinfo=(poolinfo*)arg;

        //阻塞并等待客户端的连接
        int clilen=sizeof(struct sockaddr_in);
        while(1)
        {
                struct sockinfo* pinfo;
                pinfo=(struct sockinfo*)malloc(sizeof(struct sockinfo));
                int cfd=accept(poolinfo->fd,(struct sockaddr*)&pinfo->addr,&clilen);
                pinfo->fd=cfd;//保存返回的文件描述符
                if(cfd==-1)
                {
                        perror("accept");
                        break;
                }
                //添加通信的任务
                threadPoolAdd(poolinfo->p,working,pinfo);
        }
        close(poolinfo->fd);
}

//子线程的任务函数·
void working(void *arg)
{
        struct sockinfo* pinfo=(struct sockinfo*)arg;
        //打印客户端地址
        char ip[1024]={0};
        printf("客户端IP地址:%s,端口:%d\n",inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(pinfo->addr.sin_port));
        //和客户建立通信
        while(1)
        {
                char buf[1024];
                memset(buf,0,sizeof(buf));
                int len=read(pinfo->fd,buf,sizeof(buf));
                if(len>0)
                {
                        printf("客户端say:%s\n",buf);
                        write(pinfo->fd,buf,len);
                }
                else if(len==0)
                {
                        printf("客户端断开了连接...\n");
                        break;
                }
                else
                {
                        perror("read");
                        break;
                }
        }
        close(pinfo->fd);
        pinfo->fd=-1;//将通信描述符再次初始化为-1
}
举报

相关推荐

0 条评论