月度归档:2009年11月

一个非阻塞方式的网络程序模型(UDP)

服务器端:

[ssj@main test]$ cat noneasyserver.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#define MAX 80

void my_turn(char *p)
{
if (p == NULL)return;
while( *p != '')
{
if( *p >= (char)0x61 && *p <= (char)0x7a)
*p=(char)((int)*p-(int)0x20);
p++;
}
}

int main(void)
{
struct sockaddr_in sin,cin;
int sfd;
int port=65533;
socklen_t addr_len;
char buf[MAX];
char addr_p[INET_ADDRSTRLEN];
int n,n1,flags;

bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=htons(port);

sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd==-1)
{
perror("Fail to socket");
exit(1);
}

if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1)
{
perror("Fail to bind");
exit(1);
}

flags=fcntl(sfd,F_GETFL);
flags |= O_NONBLOCK;

if(fcntl(sfd,F_SETFL,flags)==-1)
{
perror("Fail to fcntl");
exit(1);
}

while(1)
{
sleep(5);
bzero(buf,sizeof(buf));
addr_len=sizeof(sin);

n=recvfrom(sfd,buf,MAX,0,(struct sockaddr *)&cin,&addr_len);
if(n==-1&&errno!=EAGAIN)
{
perror("Fail to receiven");
exit(1);
}else if(errno==EAGAIN)
printf("socket are not ready nown");

if(n>=0)
{
inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));
printf("Client IP is %s:%dn",addr_p,ntohs(cin.sin_port));
printf("type:%sn",buf);
my_turn(buf);

n1=sendto(sfd,buf,n,0,(struct sockaddr *)&cin,addr_len);
if(n1==-1&&errno!=EAGAIN)
{
perror("Fail to sendto");exit(1);
}else if(errno==EAGAIN)
{
printf("socket ate not ready nown");
}
}

}
if(close(sfd)==-1)
{
perror("Fail to close");exit(1);
}
return 0;
}

客户端:

[ssj@main test]$ cat noneasyclient.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#define MAX 80

int main(void)
{
struct sockaddr_in sin,cin;
int port=65533;
socklen_t addr_len;
int sfd;
char buf[MAX];
char add_p[INET_ADDRSTRLEN];
int n;

bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
inet_pton(AF_INET,"127.0.0.1",&sin.sin_addr);
sin.sin_port=htons(port);

sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd==-1){perror("Fail to socket");exit(1);}

if(fgets(buf,MAX,stdin)==NULL){perror("Fail to fget");exit(1);}

n=sendto(sfd,buf,strlen(buf)+1,0,(struct sockaddr *)&sin,sizeof(sin));
if(n==-1){perror("Fail to send");exit(1);}

addr_len=sizeof(sin);

n=recvfrom(sfd,buf,MAX,0,(struct sockaddr *)&cin,&addr_len);
if(n==-1)
{
perror("Fail to receiven");
exit(1);
}else
printf("from server:%sn",buf);

if(close(sfd)==-1)
{
perror("Fail to close");exit(1);
}
return 0;

}

一个不完善的多线程服务器模型

根据:http://www.kumouse.com/article.asp?id=141
中的服务端改写而成,刚学不久,只是练练手的。有高人路过,还请指点
字符串长度n没有当参数传递,所以会是0,退出要第二次发数据才行,其实用消息处理函数,CTRL+C就可能搞定了
[ssj@main test]$ cat rs_easyserver.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#define MAX 200
#define BB 16
int k=0;
void my_turn(char *p)
{sleep(10);
if (p == NULL)return;
while( *p != '')
{
if( *p >= (char)0x61 && *p <= (char)0x7a)
*p=(char)((int)*p-(int)0x20);
p++;
}
}

typedef struct arg_struct ARG;
struct arg_struct{
int cfd;
};
void *f1(void *arg)
{
char buf[MAX];
char addr_p[BB];
int n,cfd;
ARG *p=(ARG *)arg;
cfd=p->cfd;
n=recv(cfd,buf,MAX,0);
if (n==-1)
{
perror("Fail to recv");
exit(1);
}
else if(n==0)
{
printf("the connect closedn");
close(cfd);
exit(1);
}
if (strcmp(buf,"close")==0){k=1;}
printf("type:%sn",buf);
my_turn(buf);
printf("turn type:%sn=================================n",buf);
n=send(cfd,buf,n,0);
if(n==-1){
perror("Fail to send");
exit(1);
}
if(close(cfd)==-1)
{
perror("Fail to close");
exit(1);
}

}

int main(void)
{
struct sockaddr_in sin,cin;
struct sockaddr *tmp;
int lfd,cfd;
socklen_t len;
char buf[MAX];
char addr_p[BB];
int n,err,port = 65533;
pthread_t tid;
ARG arg;
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=htons(port);

if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("Fail to create socket");
exit(1);
}

if(bind(lfd,(struct sockaddr *)&sin,sizeof(sin))==-1)
{
perror("Fail to bind");
exit(1);
}
if(listen(lfd,10)==-1)
{
perror("Fail to listen");
exit(1);
}
printf("running……….n");

while(1)
{
if((cfd=accept(lfd,(struct sockaddr *)&cin,&len))==-1)
{
perror("Fail to accept");
exit(1);
}else{
inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));
// printf("client IP is:%s:%d size:%dn",addr_p,ntohs(cin.sin_port),n);
arg.cfd=cfd;
err=pthread_create(&tid,NULL,f1,(void *)&arg);
if (err!=0){printf("%sn",strerror(err));exit(1);}
}
printf("client IP is:%s:%d Pthread:%d size:%dn",addr_p,ntohs(cin.sin_port),tid,n);
if (k==1)
{close(cfd);close(lfd);exit(0);}
}

if(close(cfd)==-1)
{
perror("Fail to close");
exit(1);
}

if(close(lfd)==-1)
{
perror("fail close");
exit(1);
}
return 0;
}

注:编译时加-lpthread参数,pthread_create不在默认库里

一个服务器模型的测试(例子)

服务器端:
[ssj@main test]$ cat easyserver.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define MAX 200 /*缓冲区大小*/
#define BB 16 /*IP地址长度 IPV4是16,IPV6是28*/
void my_turn(char *p) /*字符处理函数,小写变大写,linux下没有strupr了???*/
{
if (p == NULL)return;
while( *p != '')
{
if( *p >= (char)0x61 && *p <= (char)0x7a)
*p=(char)((int)*p-(int)0x20);
p++;
}
}

int main(void)
{
struct sockaddr_in sin,cin; /*sin本地IP地址结构,cin客户端IP地址结构*/
int lfd,cfd; /*lfd本地socket套接字描述符,cfd,由accept建立的*/
socklen_t len; /*客户端IP长度*/
char buf[MAX]; /*缓冲区*/
char addr_p[BB]; /*IP地址十进制字符串*/
int port = 65533; /*绑定的端口*/
int n; /*收到的数据长度*/
bzero(&sin,sizeof(sin)); /*初始化sin*/
sin.sin_family=AF_INET; /*定义为IPV4*/
sin.sin_addr.s_addr=INADDR_ANY; /*服务器可以接受任意地址*/
sin.sin_port=htons(port); /*把IP地址转有16位字节序,并赋值*/

lfd=socket(AF_INET,SOCK_STREAM,0); /*建立套接字*/
bind(lfd,(struct sockaddr *)&sin,sizeof(sin)); /*绑定端口与套接字*/
listen(lfd,10); /*监听,并设置最大队列为10*/
printf("running……….n");

while(1) /*循环处理客户的连接请求*/
{
cfd=accept(lfd,(struct sockaddr *)&cin,&len);
n=read(cfd,buf,MAX);
inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));
printf("client IP is:%s:%d size:%dn",addr_p,ntohs(cin.sin_port),n);
if (strcmp(buf,"close")==0) /*是否退出*/
{
write(cfd,"server done",12);
close(cfd);
close(lfd);
printf("server done.n");
exit(0);
}
printf("type:%sn",buf);
my_turn(buf);
printf("turn type:%sn=================================n",buf);
write(cfd,buf,n);
close(cfd);
}
if(close(lfd)==-1) /*收尾,实际上,上边的while是个死循环,用ctrl+c退出,或用close退出,都执行不到这里*/
{
perror("fail close");
exit(1);
}
return 0;
}

客户端:
[ssj@main test]$ cat easyclient.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define MAX 200

int main(int argc,char * argv[])
{
struct sockaddr_in pin;
struct sockaddr_in *apin=&pin;
char buf[MAX];
int sfd,port=65533;
char *str="ssj test";

if (argc>1)
{
str=argv[1];
}
bzero(&pin,sizeof(pin));
pin.sin_family=AF_INET;
inet_pton(AF_INET,"127.0.0.1",&pin.sin_addr);
pin.sin_port=htons(port);

sfd=socket(AF_INET,SOCK_STREAM,0);
connect(sfd,(struct sockaddr *)&pin,sizeof(pin));
write(sfd,str,strlen(str)+1);
read(sfd,buf,MAX);
printf("recive:%sn",buf);
close(sfd);
return 0;
}

======================================
更完善的一个版本(服务器)
[ssj@main test]$ cat easyserver.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include "ssjio.c"
#define MAX 200
#define BB 16
void my_turn(char *p)
{
if (p == NULL)return;
while( *p != '')
{
if( *p >= (char)0x61 && *p <= (char)0x7a)
*p=(char)((int)*p-(int)0x20);
p++;
}
}

int main(void)
{
struct sockaddr_in sin,cin;
int lfd,cfd;
socklen_t len;
char buf[MAX];
char addr_p[BB];
int port = 65533;
int n;
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=htons(port);

if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("Fail to create socket");
exit(1);
}

if(bind(lfd,(struct sockaddr *)&sin,sizeof(sin))==-1)
{
perror("Fail to bind");
exit(1);
}
if(listen(lfd,10)==-1)
{
perror("Fail to listen");
exit(1);
}
printf("running……….n");

while(1)
{
if((cfd=accept(lfd,(struct sockaddr *)&cin,&len))==-1)
{
perror("Fail to accept");
exit(1);
}

n=ssj_read(cfd,buf,MAX);
if (n==-1)
exit(1);
else if(n==0)
{
printf("the connect closedn");
close(cfd);
continue;
}

inet_ntop(AF_INET,&cin.sin_addr,addr_p,sizeof(addr_p));
printf("client IP is:%s:%d size:%dn",addr_p,ntohs(cin.sin_port),n);
if (strcmp(buf,"close")==0)
{
n=ssj_write(cfd,"server done",12);
if(n==-1)
exit(1);
close(cfd);
close(lfd);
printf("server done.n");
exit(0);
}
printf("type:%sn",buf);
my_turn(buf);
printf("turn type:%sn=================================n",buf);
n=ssj_write(cfd,buf,n);
if(n==-1)
exit(1);

if(close(cfd)==-1)
{
perror("Fail to close");
exit(1);
}
}
if(close(lfd)==-1)
{
perror("fail close");
exit(1);
}
return 0;
}

=========================
[ssj@main test]$ cat ssjio.c
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

ssize_t ssj_read(int fd,void *buf,size_t length)
{
ssize_t done=length;
done=read(fd,buf,length);
return done;
}

ssize_t ssj_write(int fd,void *buf,size_t length)
{
ssize_t done=length;
while(done>0)
{
done=write(fd,buf,length);
if(done!=length)
if (errno==EINTR)
done=length;
else{
perror("Fail to write");
return -1;
}
else
break;
}
return done;
}

客户端同理

关于 linux 中 进程与线程 新的理解

进程 比如用fork函数数建立的子进程,一个是重量级进程,他有自己独立的.data 与.bss 堆 和 栈,只是共享了父进程的代码段而以。
vfork共享了父进程的一切。
而说到线程,LINUX的线程的概念,我个人理解,它本来主是个轻量级的进程,线程共享父线程绝大部分资源,只有独立的栈。

这么说来,进程和线程从实质上讲没有多大区别。在linux中线程只是一个轻量级的进程而以。