• 全部
  • 系统维护与使用
  • 应用程序开发
  • 内核源代码
  • 驱动程序开发
  • CPU和硬件区
  • UNIX文化
  • Solaris
  • Power Linux
  • 问答

socket问题

darkstar21cn 2005-12-16 06:06:52
2个很简单的代码,一个服务端接受连接,一个客户端连接上去。
正常情况下没有什么问题,可以收发数据。
但是一旦我在服务端调用close()关闭连接后,客户程序在send()函数异常退出。
操作系统服务端linux 2.6.12,客户端linux 2.6.14。
...全文
247 点赞 收藏 17
写回复
17 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
痞子酷 2006-02-21
send的最后一个参数是flags,置为MSG_NOSIGNAL,就不会发送SIGPIPE信号了,而是返回EPIPE错误。
回复
Army123 2006-02-21
UP
回复
hanyufeng 2006-02-21
搂主太好了````````
回复
fierygnu 2006-02-20
send的最后一个参数是flags,置为MSG_NOSIGNAL,就不会发送SIGPIPE信号了,而是返回EPIPE错误。
回复
alaiyeshi 2006-02-18
那时候没看见你的贴子

.....
接个分算了
回复
darkstar21cn 2006-02-18
似乎都知道呀,那先前怎么没人告诉我呢?
回复
Mybox 2006-02-17
用signal (SIGPIPE, SIG_IGN);来忽略错误,当向一个关闭的socket进行write是就会产生这个信号.
回复
yanlong83 2006-02-15
来啦
回复
tonyMCM 2006-02-15
signal (SIGPIPE, SIG_IGN);
忽略管道错误 一般都要加的

回复
darkstar21cn 2006-02-15
不知道怎么给出这100分,既然问题已经解决(早解决了,很久没来csdn而已),又不能给自己分只好放分了。
100分给2位没有提什么建设性意见的,太奢侈了,所以还是大家来领分吧,前20位,一人5分。
回复
darkstar21cn 2006-02-15
先回最后一个恢复:
send()函数内异常,它后面的代码,没有用。好像我说过的吧?

自己来回答吧,虽然不能给自己分,不过让不知道的人知道一下,不能太自私吧-)
异常是由于SIGPIPE信号,这个信号是内核发出的,send的函数收到就退出了,没有给我们再处理的机会,处理方法很简单,忽略这个信号,加入下面的一行代码,就可以拦截这个信号,就能在send()之后处理错误了。

signal (SIGPIPE, SIG_IGN);
回复
tonyMCM 2005-12-26
你 可以先打出错误代码再找问题!!!
factsend = send();
if (factsend == -1)
{
printf("send error %d %s\n", errno, strerror(errno));
}
回复
darkstar21cn 2005-12-17
都睡觉去了?
郁闷。等待ing
回复
darkstar21cn 2005-12-17
日,CSDN垃圾,拷了一点,没反映了
再来
int sock = -1;
int main ()
{
while (!init_sock ())
{
usleep (5000 * 1000);
}
while (1)
{
if (send (sock, "1234567890", 10, 0) < 0)
printf ("send error");
else
printf ("send successfully");
}
return 0;
}

一开始连接正常,发送数据没问题,服务端也确定收得了正确的数据。但是,我一旦把服务端关闭之后,客户端运行到send()中异常退出。

我查了很多资料,都没有提到send会在发送失败时,导致整个程序异常退出的。哪个高手给解释解释。
回复
darkstar21cn 2005-12-17
不好意思,多拷了一行
#define CLOSESOCKET(s) do { \
shutdown ((s), SHUT_RD); \
::close((s)); \
}while (0)

客户端,很简单,就是连接上后不断的给服务端发数据。
int init_sock ()
{
sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (-1 == sock)
{
fprintf (stderr, "socket () function call error: %s\n", strerror (errno));
usleep (1000 * 1000);
return 0;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr (ip);
sin.sin_port = htons (port);
if (connect (sock, (struct sockaddr*)&sin, sizeof (sin)) == -1)
{
TRACEN ("[%s:%u]connect () function call error: %s\n", ip, port, strerror (errno));
close (sock);
sock = -1;
usleep (1000 * 1000);
return 0;
}
return 1;


int main ()
{

}
回复
khyang 2005-12-16
今天睡觉,明天来解决这个问题。
回复
darkstar21cn 2005-12-16
服务端代码:
#define CLOSESOCKET(s) do { \
shutdown ((s), SHUT_RD); \
::close((s)); \
struct timeval tv;
}while (0)

int init_sock ()
{
int err;
#ifdef WIN32
//Initialize environment for socket
WSADATA data;
err = WSAStartup (MAKEWORD (2, 2), &data);
if (err < 0)
exit (-1);
#endif
accept_ = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == accept_)
{
//print error informations
cerr << "Error create a socket" << endl;
exit (-1);
}

///If we did't set the port, it will use the default port
port_ = Config_handler::get_int ("Network", "Snap_Port", 0);
if (port_ == 0)
port_ = PORT;
struct sockaddr_in sin;
memset (&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_family = AF_INET;
sin.sin_port = htons (port_);

int val=1;
err = setsockopt (accept_, SOL_SOCKET, SO_REUSEADDR, (char const*)&val, sizeof (val));
if (err < 0)
{
CLOSESOCKET (accept_);
accept_ = INVALID_SOCKET;//define as -1
//print error information
cerr << "Error setsockopt" << endl;
return 0;
}
int len = sizeof (sin);
err = bind (accept_, (struct sockaddr*)&sin, len);
if (-1 == err)
{
CLOSESOCKET (accept_);
accept_ = INVALID_SOCKET;
//print error information
return 0;
}
err = listen (accept_, MAX_CONNECTIONS);//define as 100
cerr << "Begin listen sniffer connection" << endl;
if (-1 == err)
{
CLOSESOCKET (accept_);
accept_ = INVALID_SOCKET;
cerr << "Error calling listen () function" << endl;
return 0;
}
return 1;
}

void svc ()
{
while (INVALID_SOCKET == accept_)
{
Sleep (1000);
init_sock ();
}

cerr << "Begin accept connection from known host." << endl;
while (processing_)
{
struct sockaddr_in sin;
socklen_t len = sizeof (sin);

SSL_SOCKET client = accept (accept_, (sockaddr*)&sin, &len);
if (INVALID_SOCKET != client)
{
//check the connection, it must connected
char ip[16];
sprintf (ip, "%u.%u.%u.%u", NIPQCHAR (sin.sin_addr.s_addr));
cerr << "Commint a connection from " << ip << endl;
//verify the connection
Connection_handler* h = Connection_handler::get_handler_ip (ip);
if (NULL == h)
{
cerr << "Unknown host ip(" << ip << "), refuse it" << endl;
shutdown (client, SHUT_RDWR);//CLOSESOCKET (client);//OK here if I shutdown or close the socket, the client will quit when it want to send something
}
else
{
arg_struct* args = new arg_struct ();
args->ibox = h->get_iboxid ();
args->sock = client;
THREAD_TYPE pid;
THREAD_CREATE (pid, do_connection, args);//thus create a thread
}
}
Sleep (0);
}
回复
发帖
Linux/Unix社区
创建于2007-08-27

2.0w+

社区成员

Linux/Unix社区 应用程序开发区
申请成为版主
帖子事件
创建了帖子
2005-12-16 06:06
社区公告
暂无公告