- 论坛徽章:
- 0
|
自己实现的UDP服务器模型存在一点问题。
先上代码:
服务端的:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define MYPORT 4567 //well-known port
#define MAXLINE 4096
static int fd1[2], fd2[2] ;
static char msg[MAXLINE] = {'\0'} ;
int global_sockfd;
struct sockaddr_in pool[VOLUME];
struct sockaddr_in global_from_addr;
//-----------------------------------------------------------------------------
void start_newsrv(struct sockaddr_in newfrom_addr){
printf("start new srv\n");
static int i = 0;
static pid_t pid;
int sockfd;
int addr_len;
static int port = MYPORT;
char newport[5] = {'\0'};
struct sockaddr_in newsrv_addr;
addr_len = sizeof(newfrom_addr);
if( (pid = fork()) < 0 )
printf("fork error!\n");
else if (pid > 0){ //create new socket using new port number
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
int opt = 1;
/*if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
&opt, sizeof(opt)) != 0){
perror("Server setsockopt failed" ;
}
*/
port++;
printf("prepare new port(in srv ):%d\n",port);
bzero((char *) &newsrv_addr, sizeof(newsrv_addr));
newsrv_addr.sin_family = AF_INET;
newsrv_addr.sin_port = htons(port); //new port number
newsrv_addr.sin_addr.s_addr = INADDR_ANY;
if( bind(sockfd,(struct sockaddr *)&newsrv_addr,
sizeof(newsrv_addr)) == -1){
perror("bind");
exit(1);
}
sprintf(newport,"%d",port);
printf("new srv ok,send to client new port\n");
//send client new port info
if (-1 == sendto(global_sockfd,newport,strlen(newport),0,
(struct sockaddr *)&newfrom_addr,
sizeof(newfrom_addr)) ){
perror("sendto");
}
printf("send new port ok\n");
do{ //comumunicate with client through new socket
if ( recvfrom(sockfd, msg, MAXLINE, 0,
(struct sockaddr *)&newfrom_addr, &addr_len) < 0 ){
perror("recvfrom error");
}
int count = 0 ;
printf("receive msg times:%d\n",++count);
if (-1 == sendto(sockfd,msg, MAXLINE, 0,
(struct sockaddr *)&newfrom_addr,sizeof(newfrom_addr)) ){
perror("sendto cli through new udpsrv error");
}
}while(1);
}
}
//-----------------------------------------------------------
int handle_request(int global_sockfd){
int len;
int recvlen;
int count = 0;
again:
recvlen = recvfrom(global_sockfd, msg, MAXLINE,
0,(struct sockaddr *) &global_from_addr, &len);
//部分错误处理以及hash的代码,与问题没有太大关联,略去不计
start_newsrv(global_from_addr);
goto again;
}
}
void main()
{
struct sockaddr_in srv_addr;
memset(pool,'\0',sizeof(pool));
if ((global_sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
// .......
if( bind(global_sockfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr)) == -1) {
perror("bind");
exit(1);
}
printf("udp srv end ok...\n");
handle_request(global_sockfd);
}
|
服务器模型已经运行成功,唯一有问题的就是那个setsockopt函数的地方,当灰色部分标示的代码被注释掉后,运行结果就是:
只能有一个客户端请求成功,当新的客户端来请求时,服务端的错误处理部分会出现bind error address already in use 的错误。
这里我不解的地方就是,在服务端新建立的socket使用的port和原先的port并不一样啊(有port++操作),并且:
newsrv_addr.sin_addr.s_addr = INADDR_ANY;
那为什么还会提示address 已经被使用的信息呢?
当灰色部分不被注释掉,运行结果是正常的,也可以完成服务器的模型,但有问题,见附件1。
就是当多于一个客户端请求服务端时,在服务端中的port++操作不会成功执行。
大家帮看下问题存在哪里吧,小弟实在是无能为力了,谢谢大家了。  |
|