单次服务器server(又可称为迭代式服务器程序)
#include "unp.h"
int main(int argc, char **argcv){
int listenfd,connfd;
pid_t childpid;
socksize_len clilen;
struct sockaddr_in servaddr,cliaddr;
listenfd = Socket(FP_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_finally = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADRR_ANY);
servaddr.sin_port = htons(SERVPORT);
Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
Listen(listenfd, BACKLOG);
for(;;){
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA*)&cliaddr, clilen);
Close(listenfd);
str_echo(connfd);
Close(connfd);
}
return 0;
}
void str_echo(int sockfd){
ssize_t n;
char buf[MAXLINE];
again:
while((n = read(sockfd, buf , MAXLINE))>0){
Writen(sockfd, buf, n);
}
if(n<0 && erron == EINTR)
goto again;
else if(n<0)
err_sys("str_echo: read error");
}
单次服务器多次循环成为迭代式服务器,其中for()控制循环次数。假如循环五次,则只需要改for循坏,改为如下
for(int i = 0 ; i < 5 ; i++){
}
多进程服务器
#include "upn.h"
char buffer[BUFFER_SIZE];
int main(int argc, char* argcv[]){
int listenfd, connfd;
size_t clilen;
struct sockaddr_in cliaddr,servaddr;
signal(SIGCHLD, SIG_IGN);
listenfd = Socket(PF_INET, SOCK_STREAM, 0);
bzero(&servaddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
seraddr.sin_port = htons(SERVPORT)
Bind(listenfd, (struct sockaddr_in*)& servaddr, sizeof(servaddr));
Listen(listenfd, BACKLOG);
while(1){
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr_in*)&cliaddr, clilen);
//开始做判断了
if(connfd < 0 && connfd == EINTR) continue;
if(Fork() == 0){
Close(listenfd);
str_echo2(connfd, buffer);
Close(connfd);
return 0
}
Close(listenfd);
}
Close(connfd);
Return 0;
}
void str_echo2(int sockfd, char* buf)
{
ssize_t n;
while (1) {
n = Read(sockfd, buf, BUFFER_SIZE);
if (n > 0)
Write(sockfd, buf, n);
else
return;
}
}
ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = read(fd, ptr, nbytes)) == -1){
if (errno == ECONNRESET) {
err_msg("reset by peer");
return 0;
}
else err_sys("read error");
}
return(n);
}
单次client
#include"unp.h"
int main(int argc, char **argv){
int sockfd;
struct sockaddr_in servaddr;
if(argc!=2){
err_quit("");
}
sockfd = Socket(PF_INET, SOCK_STERAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));
str_cli(stdin, sockfd);
exit(0);
}
void str_cli(FILE *fp, int sockfd){
char sendline[MAXLINE],recvline[MAXLINE];
while(Fgets(sendline, MAXLINE, fp)!=NULL){
Writen(sockfd, sendline, sizeof(sendline));
if(Readline(sockfd, recvline, MAXLINE)==0) //服务器过早终止
err_quit("str_cli: server terminated permaturely");
Fput(recvline, stdout);
}
}
将上述fp改为标准输入,也可以写为如格式:
#define PORT 1234
#define MAXLINE 100
int main(){
/*
同上
*/
str_cli(sockfd);
}
void str_cli(int sockfd){
char sendline[MAXLINE],readline[MAXLINE];
char time[100];
int i,datanum=0;
while(scanf("%s",time)){
Writen(sockfd, time, sizeof(time));
datanum = read(sockfd, readline, MAXLINE);
recvline[datanum] = '\0';
printf("服务器返回消息:%s",recvline);
}
}
注意: (struct sockaddr_in *)&servaddr 和 (SA*)&servaddr的用法和意义是一样的,但是由于前者是linux包,后者是unp包,所以表达不同。