linux多进程网络实例,Linux下一个单进程并发服务器的实例 使用select
/*單進程并發服務器實例。該程序采用單進程并發服務器算法實現的。*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 1234?????????? //服務器端口
#define BACKLOG 5?????????? //listen隊列中等待的連接數
#define MAXDATASIZE 1024 //緩沖區大小
typedef struct _CLIENT{??????? //客戶端結構體
int?????? fd;??????? //客戶端socket描述符
char*? name;
struct sockaddr_in addr;???? //客戶端地址信息結構體
char* data;
} CLIENT;
void process_cli(CLIENT *client, char* recvbuf, int len);? //客戶請求處理函數
void savedata(char* recvbuf, int len, char* data);
main()
{
int??? i, maxi, maxfd,sockfd;
int??? nready;
ssize_t????? n;
fd_set????? rset, allset;??? //select所需的文件描述符集合
int listenfd, connectfd;???? //socket文件描述符
struct sockaddr_in server;???? //服務器地址信息結構體
CLIENT client[FD_SETSIZE];???? //FD_SETSIZE為select函數支持的最大描述符個數
char recvbuf[MAXDATASIZE];??? //緩沖區
int sin_size;??????????? //地址信息結構體大小
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {??? //調用socket創建用于監聽客戶端的socket
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));??? //設置socket屬性
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {??? //調用bind綁定地址
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){????? //調用listen開始監聽
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
//初始化select
maxfd = listenfd;
maxi = -1;
for (i = 0; i < FD_SETSIZE; i++) {
client[i].fd = -1;
}
FD_ZERO(&allset);??????? //清空
FD_SET(listenfd, &allset);??? //將監聽socket加入select檢測的描述符集合
while(1)
{
struct sockaddr_in addr;
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);??? //調用select
printf("select saw rset actions and the readfset num is %d. \n",nready );
if (FD_ISSET(listenfd, &rset)) {????? //檢測是否有新客戶端請求
printf("accept a connection.\n");
//調用accept,返回服務器與客戶端連接的socket描述符
if ((connectfd = accept(listenfd,(struct sockaddr *)&addr,(socklen_t *)&sin_size))==-1) {
perror("accept() error\n");
continue;
}
//將新客戶端的加入數組
for (i = 0; i < FD_SETSIZE; i++){
if (client[i].fd < 0) {
client[i].fd = connectfd;??? //保存客戶端描述符
client[i].name = new char[MAXDATASIZE];
client[i].addr = addr;
client[i].data = new char[MAXDATASIZE];
client[i].name[0] = '\0';
client[i].data[0] = '\0';
printf("You got a connection from %s.? ",inet_ntoa(client[i].addr.sin_addr) );
break;
}
}
printf("add new connect fd.\n");
if (i == FD_SETSIZE)
printf("too many clients\n");
FD_SET(connectfd, &allset);?? //將新socket連接放入select監聽集合
if (connectfd > maxfd)
maxfd = connectfd;?? //確認maxfd是最大描述符
if (i > maxi)????????? //數組最大元素值
maxi = i;
if (--nready <= 0)
continue;????? //如果沒有新客戶端連接,繼續循環
}
for (i = 0; i <= maxi; i++) {
if ( (sockfd = client[i].fd) < 0)?????? //如果客戶端描述符小于0,則沒有客戶端連接,檢測下一個
continue;
if (FD_ISSET(sockfd, &rset)) {??????? //檢測此客戶端socket是否有數據
printf("recv occured for connect fd[%d].\n",i);
if ( (n = recv(sockfd, recvbuf, MAXDATASIZE,0)) == 0) { //從客戶端socket讀數據,等于0表示網絡中斷
close(sockfd);??????? //關閉socket連接
printf("Client( %s ) closed connection. User's data: %s\n",client[i].name,client[i].data);
FD_CLR(sockfd, &allset);??? //從監聽集合中刪除此socket連接
client[i].fd = -1;??????? //數組元素設初始值,表示沒客戶端連接
delete client[i].name;
delete client[i].data;
} else
process_cli(&client[i], recvbuf, n);??? //接收到客戶數據,開始處理
if (--nready <= 0)
break;?????? //如果沒有新客戶端有數據,跳出for循環回到while循環
}
}
}
close(listenfd);? //關閉服務器監聽socket
}
void process_cli(CLIENT *client, char* recvbuf, int len)
{
char sendbuf[MAXDATASIZE];
recvbuf[len-1] = '\0';
if (strlen(client->name) == 0) {
memcpy(client->name,recvbuf, len);
printf("Client's name is %s.\n",client->name);
return;
}
printf("Received client( %s ) message: %s\n",client->name, recvbuf);
savedata(recvbuf,len, client->data);
for (int i1 = 0; i1 < len - 1; i1++) {
sendbuf[i1] = recvbuf[len - i1 -2];
}
sendbuf[len - 1] = '\0';
send(client->fd,sendbuf,strlen(sendbuf),0);
}
void savedata(char* recvbuf, int len, char* data)
{
int start = strlen(data);
for (int i = 0; i < len; i++) {
data[start + i] = recvbuf[i];
}
}
總結
以上是生活随笔為你收集整理的linux多进程网络实例,Linux下一个单进程并发服务器的实例 使用select的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux目录怎么自动生成,情景linu
- 下一篇: linux 拆分文件 多个,linux把