传智扫地僧课程学习笔记。
中间直接复制代码的时候,出了一个错误,
说明下,
客户端,就一个套接字,所以收发都是通过它来完成,
服务器端,是通过accept返回的链接来进行通信的,不是最开始那个(因为已经用于listen了),
tcp/ip是流式的,
当客户端主动关闭后,会发送一个FIN信号,
可是你通过 ps -u | grep 用户名,
发现,服务器程序还在运行,
原来是服务器有2个进程,
一个进程检测到客户端关闭后,就关闭了,
另一个进程,也就是子进程,没人管,就一直嘎在那,
所以我们需要服务器父进程,发一个信号给子进程,让它关闭,
下面是代码,
在信号发送中,有个地方不明白啊,??怎么在父进程中kill的pid是自己的pid,不是应该是子进程的id吗,
这是服务器代码,
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
void handle( int num)
{
printf("recv num:%d\n", num);
exit( 0);
}
int main()
{
int sockfd = 0;
signal( SIGUSR1, handle);
sockfd = socket( PF_INET, SOCK_STREAM, 0);
if( -1 == sockfd )
{
perror("fun socket\n");
exit( 0);
}
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8001);
srvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int optval = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))
< 0)
{
perror("setsockopt bind\n");
exit(0);
}
if( bind( sockfd, (struct sockaddr *)&srvaddr, sizeof( srvaddr)) <0)
{
perror("socket\n");
exit( 0);
}
if( listen( sockfd, SOMAXCONN) <0)
{
perror( "fun listen\n");
exit( 0);
}
//struct sockaddr peeraddr,
//socklen_t peerlen;
struct sockaddr_in perraddr;
socklen_t perrlen = sizeof( perraddr);
unsigned int conn = 0;
conn = accept( sockfd, (struct sockaddr *)&perraddr, (socklen_t *)&perrlen);
if( conn == -1)
{
perror("fun listen\n");
exit( 0);
}
int pid;
pid = fork();
if( pid>0 )
{
char revbuf[1024] = {0};
int ret;
while(1)
{
ret = read( conn, revbuf, sizeof( revbuf));
if( ret==0)
{
printf("duifang guanbile");
break;
}
else if( ret<0)
{
perror("read fail\n");
exit( 0);
}
fputs( revbuf, stdout);
//write( conn, revbuf, ret);
memset( revbuf, 0, sizeof( revbuf));
}
kill( pid, SIGUSR1);
}
else
{
char sendbuf[1024] = {0};
while( fgets(sendbuf, sizeof(sendbuf), stdin)!=NULL)
{
write( conn, sendbuf, strlen(sendbuf));
//read( sockfd, revbuf, sizeof(revbuf));
//fputs( revbuf, stdout);
//memset( revbuf, 0, sizeof(revbuf));
memset( sendbuf, 0, sizeof(sendbuf));
}
}
close( conn);
close( sockfd);
return 0;
}
/*
accept返回一个新的,
*/
这是客户端代码,
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main()
{
int sockfd = 0;
sockfd = socket( PF_INET, SOCK_STREAM, 0);
if( sockfd == -1 )
{
perror(" fun socket\n");
exit(0);
}
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8001);
srvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if( connect( sockfd, ( struct sockaddr*)(&srvaddr), sizeof( srvaddr))<0)
{
perror("connect");
exit( 0);
}
int pid = 0;
pid = fork();
if( pid > 0)
{
//char revbuf[1024] = {0};
char sendbuf[1024] = {0};
while( fgets(sendbuf, sizeof(sendbuf), stdin)!=NULL)
{
write( sockfd, sendbuf, strlen(sendbuf));
//read( sockfd, revbuf, sizeof(revbuf));
//fputs( revbuf, stdout);
//memset( revbuf, 0, sizeof(revbuf));
memset( sendbuf, 0, sizeof(sendbuf));
}
}
else if( pid == 0)
{
char revbuf[1024] = {0};
while( 1)
{
read( sockfd, revbuf, sizeof(revbuf));
fputs( revbuf, stdout);
memset( revbuf, 0, sizeof(revbuf));
}
}
close( sockfd);
return 0;
}