客戶端服務器斷開連接後,新連接在描述符號不變情況下,是否可以繼續通信?
當然可以,描述符指定了一個socket通信,描述符號相同,無論socket使用方式是否變化或者重新連接,使用原來描述符的部分不受影響。
測試程序:
客戶端:
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#define NEAS_SERVER_SOCKET_PATH "/neteye/var/domin_as.unix"
int ERR = -1;
int OK = -1;
int sockfd = -1;
struct pollfd poll_array[2];
int
init()
{
struct sockaddr_un sockaddr_v;
memset(&sockaddr_v,0,sizeof(struct sockaddr_un));
sockfd = socket(PF_UNIX,SOCK_STREAM,0);
if(sockfd < 0){
perror("socket\n");
return ERR;
}else{
fcntl(sockfd,F_SETFL,O_NONBLOCK);
sockaddr_v.sun_family = PF_UNIX;
bzero(sockaddr_v.sun_path,sizeof(sockaddr_v.sun_path));
strcpy(sockaddr_v.sun_path,NEAS_SERVER_SOCKET_PATH);
if(connect(sockfd,(struct sockaddr*)&sockaddr_v,sizeof(sockaddr_v))<0)
{
close(sockfd);
printf("errorno %d\n",errno);
perror("connect");
return ERR;
}
poll_array[0].fd = sockfd;
poll_array[0].events = POLLIN|POLLPRI|POLLOUT|POLLHUP;
}
}
int
main()
{
int ret = 0;
init();
if(sockfd<0)
{
perror("init");
return ERR;
}
int buf[100] = {0};
while(1)
{
printf("begin poll\n");
ret = poll(poll_array, 2, 10000);
printf("poll ret: %d\n",ret);
printf("poll revents ret: %d\n",poll_array[0].revents);
if(poll_array[0].revents & POLLHUP)
{
printf("POLLHUP and reinit\n" );
close(poll_array[0].fd);
init();
if(sockfd<0)
{
perror("init");
return ERR;
}
poll_array[0].fd = sockfd;
poll_array[0].events = POLLIN|POLLPRI|POLLOUT|POLLHUP;
}
if(poll_array[0].revents & POLLIN)
{
printf("POLLIN\n");
ret = read(poll_array[0].fd, buf, 100);
printf("reat ret: %d\n",ret);
printf("read buf = %s\n", buf);
}
if(poll_array[0].revents & POLLOUT)
{
printf("POLLOUT\n");
ret = write(poll_array[0].fd, "client", 9);
printf("write ret = %d\n", ret);
}
sleep(2);
}
return 0;
}
服務端:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#define NEAS_SERVER_SOCKET_PATH "/neteye/var/domin_as.unix"
int ERR = -1;
int OK = -1;
int
main()
{
struct sockaddr_un sockaddr_v;
memset(&sockaddr_v,0,sizeof(struct sockaddr_un));
int sockfd = -1;
int ret =0;
sockfd = socket(PF_UNIX,SOCK_STREAM,0);
if(sockfd < 0){
perror("socket\n");
return ERR;
}else{
fcntl(sockfd,F_SETFL,O_NONBLOCK);
sockaddr_v.sun_family = PF_UNIX;
bzero(sockaddr_v.sun_path,sizeof(sockaddr_v.sun_path));
strcpy(sockaddr_v.sun_path,NEAS_SERVER_SOCKET_PATH);
int nOptval = 1;
ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&nOptval, sizeof(int));
if (ret<0)
{
perror("setsock\n");
return ERR;
}
if(bind(sockfd,(struct sockaddr*)&sockaddr_v,sizeof(struct sockaddr_un)) < 0)
{
perror("bind\n");
return ERR;
}
}
if(listen(sockfd, 10) < 0)
{
perror("listen\n");
return ERR;
}
struct pollfd poll_array[10];
poll_array[0].fd = sockfd;
poll_array[0].events = POLLIN|POLLPRI;
ret = 0;
int sockfd_c = -1;//新連接用
int sockfd_old = -1;//斷開的連接
int buf[100] = {0};
int i = 0;
while(1)
{
printf("begin poll\n");
ret = poll(poll_array, 11, 1000000);
if(ret<0)
{
perror("poll\n");
return ERR;
}
if(ret>0)
{
if(poll_array[0].revents & POLLIN)
{
sockfd_c = accept(sockfd,NULL,NULL);
printf("new connect fd: %d\n",sockfd_c);
poll_array[1].fd = sockfd_c;
poll_array[1].events = POLLIN|POLLPRI;
}
if(poll_array[1].revents & POLLIN)
{
ret = read(poll_array[1].fd, buf, 100);
printf("read ret = %d\n", ret);
printf("read buf = %s\n", buf);
if(i<5)
{
++i;
ret = write(poll_array[1].fd, "new socket", 15);
printf("new write ret = %d\n", ret);
}
}
}
if(i>5)
{
printf("old write fd = %d\n", sockfd_old);
ret = write(sockfd_old, "old socket", 15);
printf("old write ret = %d\n", ret);
}
if(i==5)
{
printf("\n\nclose fd\n\n");
close(sockfd_c);
sockfd_old = sockfd_c;
++i;
}
sleep(2);
}
return 0;
}
測試結果:
[root@localhost tmp]# ./s
begin poll
begin poll
begin poll
new connect fd: 4
begin poll
read ret = 18
read buf = client
new write ret = 15
begin poll
read ret = 9
read buf = client
new write ret = 15
begin poll
read ret = 9
read buf = client
new write ret = 15
begin poll
read ret = 9
read buf = client
new write ret = 15
begin poll
read ret = 9
read buf = client
new write ret = 15
close fd
begin poll
new connect fd: 4
old write fd = 4
old write ret = 15
begin poll
read ret = 18
read buf = client
old write fd = 4
old write ret = 15
begin poll
read ret = 9
read buf = client
old write fd = 4
old write ret = 15
begin poll
read ret = 9
read buf = client
old write fd = 4
old write ret = 15
begin poll
read ret = 9
read buf = client
old write fd = 4
old write ret = 15
[root@localhost tmp]# ./c
begin poll
poll ret: 1
poll revents ret: 4
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 4
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = new socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = new socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = new socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = new socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 21
POLLHUP and reinit
POLLIN
reat ret: -1
read buf = new socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = old socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = old socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = old socket
POLLOUT
write ret = 9
begin poll
poll ret: 1
poll revents ret: 5
POLLIN
reat ret: 15
read buf = old socket
POLLOUT
write ret = 9
排錯與調試:
1. Socket客戶端connect errno111錯誤 Connection refused:
看下服務器是否正常監聽端口
2. poll 監聽的描述在對端 CTRL+C 或者close時,返回16,即POLLHUP。
3. perror只有在出錯時可以使用,否則打印:Illegal seek