功能:实现多客户端连接的回射服务器,防止出现粘包。
server.c
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <stdio.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
#include <unistd.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <fcntl.h>
-
#include <sys/shm.h>
-
#include<errno.h>
-
-
#define MYPORT 8887
-
#define QUEUE 20
-
#define BUFFER_SIZE 1024
-
struct packet
-
{
-
int len;
-
char buf[BUFFER_SIZE];
-
};
-
ssize_t readn(int fd,void*buf,size_t count) ///用readn函数,防止在广域网上发生粘包
-
{
-
size_t nleft = count;
-
ssize_t nread;
-
char *bufp =(char*)buf;
-
while(nleft>0)
-
{
-
if((nread =read(fd,bufp,nleft))<0)
-
{
-
if(errno ==EINTR)
-
continue;
-
return -1;
-
}
-
else if(nread ==0)
-
return count - nleft;
-
-
bufp +=nread;
-
nleft -=nread;
-
-
}
-
return count;
-
}
-
ssize_t writen(int fd,const void*buf,size_t count) ///用writen函数,防止在广域网上发生粘包
-
{
-
size_t nleft=count;
-
ssize_t nwritten;
-
char *bufp=(char*)buf;
-
while(nleft>0)
-
{
-
if((nwritten =write(fd,bufp,nleft))<0)
-
{
-
if(errno ==EINTR)
-
continue;
-
return -1;
-
}
-
else if(nwritten ==0)
-
continue;
-
-
bufp +=nwritten;
-
nleft -=nwritten;
-
-
}
-
return count;
-
}
-
void do_service(int conn)
-
{
-
-
struct packet recvbuf;
-
int n;
-
while(1)
-
{
-
memset(&recvbuf,0,sizeof(recvbuf));
-
int ret = readn(conn, &recvbuf.len, 4);
-
if (ret ==-1)
-
{
-
perror("read");
-
exit(1);
-
}
-
else if(ret <4)
-
{
-
printf("client close\n");
-
-
break;
-
}
-
n=ntohl(recvbuf.len);
-
ret =readn(conn,recvbuf.buf,n);
-
if (ret ==-1)
-
{
-
perror("read");
-
exit(1);
-
}
-
else if(ret <n)
-
{
-
printf("client close\n");
-
-
break;
-
}
-
-
fputs(recvbuf.buf, stdout);
-
writen(conn, &recvbuf, 4+n);
-
}
-
}
-
int main()
-
{
-
-
-
///定义sockfd
-
int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
-
-
///定义sockaddr_in
-
struct sockaddr_in server_sockaddr;
-
server_sockaddr.sin_family = AF_INET;
-
server_sockaddr.sin_port = htons(MYPORT);
-
server_sockaddr.sin_addr.s_addr = inet_addr("127.0.0.2");
-
-
///bind,成功返回0,出错返回-1
-
int on =1; ///获得IP地址和端口
-
if(setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==-1) ///实现IP地址的重复利用,防止出现address used
-
{
-
perror("setsockopt");
-
exit(1);
-
}
-
printf("ip=%s port=%d\n",inet_ntoa(server_sockaddr.sin_addr),ntohs(server_sockaddr.sin_port));
-
if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
-
{
-
perror("bind");
-
exit(1);
-
}
-
-
///listen,成功返回0,出错返回-1
-
int listenfd=listen(server_sockfd,QUEUE) ;
-
if(listenfd<0)
-
{
-
perror("listen");
-
exit(1);
-
}
-
-
///客户端套接字
-
-
struct sockaddr_in client_addr;
-
socklen_t length = sizeof(client_addr);
-
-
///成功返回非负描述字,出错返回-1
-
-
int conn ;
-
pid_t pid; ///fork 多个进程
-
while(1) ///多个客户端连接
-
{ if((conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length))<0)
-
{
-
perror("accept");
-
exit(1);
-
}
-
pid =fork();
-
if(pid==-1)
-
{
-
perror("fork");
-
exit(1);
-
}
-
if(pid==0) ///子进程
-
{
-
close(server_sockfd);
-
do_service(conn);
-
exit(1);
-
}
-
else ///父进程
-
-
close(conn);
-
-
}
-
-
return 0;
-
}
client.c:
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <stdio.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
#include <unistd.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <fcntl.h>
-
#include <sys/shm.h>
-
#include<errno.h>
-
-
#define MYPORT 8887
-
#define QUEUE 20
-
#define BUFFER_SIZE 1024
-
struct packet
-
{
-
int len;
-
char buf[BUFFER_SIZE];
-
};
-
ssize_t readn(int fd,void*buf,size_t count) ///用readn函数,防止在广域网上发生粘包
-
{
-
size_t nleft = count;
-
ssize_t nread;
-
char *bufp =(char*)buf;
-
while(nleft>0)
-
{
-
if((nread =read(fd,bufp,nleft))<0)
-
{
-
if(errno ==EINTR)
-
continue;
-
return -1;
-
}
-
else if(nread ==0)
-
return count - nleft;
-
-
bufp +=nread;
-
nleft -=nread;
-
-
}
-
return count;
-
}
-
ssize_t writen(int fd,const void*buf,size_t count) ///用writen函数,防止在广域网上发生粘包
-
{
-
size_t nleft=count;
-
ssize_t nwritten;
-
char *bufp=(char*)buf;
-
while(nleft>0)
-
{
-
if((nwritten =write(fd,bufp,nleft))<0)
-
{
-
if(errno ==EINTR)
-
continue;
-
return -1;
-
}
-
else if(nwritten ==0)
-
continue;
-
-
bufp +=nwritten;
-
nleft -=nwritten;
-
-
}
-
return count;
-
}
-
-
int main()
-
{
-
///定义sockfd
-
int sock= socket(AF_INET,SOCK_STREAM, 0);
-
if (sock<0)
-
-
{
-
perror("sock");
-
exit(1);
-
}
-
struct sockaddr_in servaddr;
-
memset(&servaddr,0,sizeof(servaddr));
-
-
-
///定义sockaddr_in
-
-
servaddr.sin_family = AF_INET;
-
servaddr.sin_port = htons(MYPORT);
-
servaddr.sin_addr.s_addr = inet_addr("127.0.0.2");
-
-
///bind,成功返回0,出错返回-1
-
-
if (connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
-
{
-
perror("connect");
-
exit(1);
-
} ///获得IP地址和端口
-
printf("ip=%s port=%d\n",inet_ntoa(servaddr.sin_addr),ntohs(servaddr.sin_port));
-
struct packet sendbuf;
-
struct packet recvbuf;
-
memset(&sendbuf,0,sizeof(sendbuf));
-
memset(&recvbuf,0,sizeof(recvbuf));
-
int n;
-
while (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) != NULL) ///键盘输入
-
{
-
n=strlen(sendbuf.buf);
-
sendbuf.len=htonl(n);
-
writen(sock,&sendbuf,4+n);
-
int ret = readn(sock, &recvbuf.len, 4);
-
if (ret ==-1)
-
{
-
perror("read");
-
exit(1);
-
}
-
else if(ret <4)
-
{
-
printf("client close\n");
-
-
break;
-
}
-
n=ntohl(recvbuf.len);
-
ret =readn(sock,recvbuf.buf,n);
-
if (ret ==-1)
-
{
-
perror("read");
-
exit(1);
-
}
-
else if(ret <n)
-
{
-
printf("client close\n");
-
-
break;
-
}
-
-
fputs(recvbuf.buf,stdout);
-
memset(&sendbuf,0,sizeof(sendbuf));
-
memset(&recvbuf,0,sizeof(recvbuf));
-
}
-
close(sock);
-
return 0;
-
}
阅读(1492) | 评论(0) | 转发(0) |