关于TCP套接字编程中的send()引起的断开的通道
2013-10-29 19:23
218 查看
在用多线程编写可以支持多个客户端连接的远程控制系统时,当非正常关闭客户端时服务器老出现断开的通道;
原来的代码,
运行结果,当非正常关闭客户端时,服务器会出现断开的通道,
首先,自己上网搜了一下Socked send函数的用法,
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
上面一段文字来自:http://www.cnblogs.com/cgun/archive/2010/05/25/1743636.html
也正是这个原因才出现了上面所说的断开的通道的错误。
我调试程序发现当我们关闭客户端的窗口时,服务器仍会接收到一连串的东西,当服务器端接收到来自客户端的命令时(当然这不是真正有意义的命令),服务器就会响应客户端,通过send函数把buf中的数据copy到server的发送缓冲区它就返回了。由于此时c/s连接已经断开,这些数据并没有被发送出去。接着服务器接收下一个指令,并继续调用send函数去响应客户端,由于上次东西没被发送出去,所以就出现了SOCKET_ERROR,并终止了当前进程,从而出现了断开的通道。
解决方法很简单:其实也是本人了解太少了,,如果连接断开recv()函数会返回一个0,我们对其进行处理就行了。
貌似和send没关,但这个错误却促使我去认真了解了send函数
原来的代码,
#include<stdlib.h> #include<stdio.h> #include<sys/socket.h> #include<netdb.h> #include<string.h> #include<unistd.h> #include<netinet/in.h> #include<arpa/inet.h> #include<pthread.h> #define PORT 8900 #define SIZE 2048 FILE *mypopen(char *command,char type) { int pipefd[2]; pid_t pid; char *argv[10]; int i; if(pipe(pipefd)<0) { printf("create mypopen fail"); return NULL; } pid = fork(); if(pid==0) { if(type=='r') { close(pipefd[0]); dup2(pipefd[1],STDOUT_FILENO); close(pipefd[1]); } execl("/bin/sh","sh","-c",command,(char *) 0); _exit(0); } else if(pid>0) { wait(0); if(type=='r') { close(pipefd[1]); return fdopen(pipefd[0],"r"); } } } void exec (char* command,char* result) { FILE * in; int len; char c; len=0; bzero(result,sizeof(result)); in=mypopen(command,'r'); if (NULL==in) { fprintf(stderr,"error in create a pipe\n"); } while(((c=fgetc(in))!=EOF)&&(len<SIZE)) { result[len]=c; len++; } result[len]='\0'; if (0==len) { sprintf(result,"%s cannot execute\n",command); } } void serverItem(void *a) { int connectd = (int)a; char send_buf[2048]; char recv_buf[2048]; char cmd[2048]; int recvnum; int rvalue; char path[2048]; bzero(cmd,10); bzero(path,2048); while(1) { memset(send_buf,0,2048); memset(recv_buf,0,2048); recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0); if (0>recvnum) { perror("recv error\n"); continue; } recv_buf[recvnum]='\0'; sscanf(recv_buf,"%s %s",cmd,path); if ((0==strcmp("cd",cmd)) ||(0==strcmp("CD",cmd))) { chdir(path); printf("%s",path); continue; } if (0==strcmp("quit\n",recv_buf)) { continue; } else { exec(recv_buf,send_buf); } rvalue=-1; rvalue=send(connectd,send_buf,strlen(send_buf),0); if (0>rvalue) { fprintf(stderr,"error in sending data\n"); continue; } } } int main(int argc,char** argv) { struct sockaddr_in server; struct sockaddr_in client; int len; int port; int listend; int connectd; int sendnum; int opt; int sockfd; pthread_t thread; //if (2==argc) sockfd=-1; bzero(&client,sizeof(struct sockaddr)); bzero(&server,sizeof(struct sockaddr)); len=-1; port=PORT; opt=SO_REUSEADDR; if (-1==(listend=socket(AF_INET,SOCK_STREAM,0))) { perror("create listen socket error\n"); exit(1); } setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); #ifdef DEBUG printf("the listen id is %d\n",listend); #endif memset(&server,0,sizeof(struct sockaddr_in)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(port); if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr))) { perror("bind error\n"); exit(1); } if (-1==listen(listend,5)) { perror("listen error\n"); exit(1); } len = sizeof(struct sockaddr); while (1) { if (-1==(connectd=accept(listend,(struct sockaddr*)&client,&len))) { perror("create connect socket error\n"); continue; } pthread_create(&thread,NULL,(void*)serverItem,(void *)connectd); } close(listend); return 0; }
运行结果,当非正常关闭客户端时,服务器会出现断开的通道,
首先,自己上网搜了一下Socked send函数的用法,
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
上面一段文字来自:http://www.cnblogs.com/cgun/archive/2010/05/25/1743636.html
也正是这个原因才出现了上面所说的断开的通道的错误。
我调试程序发现当我们关闭客户端的窗口时,服务器仍会接收到一连串的东西,当服务器端接收到来自客户端的命令时(当然这不是真正有意义的命令),服务器就会响应客户端,通过send函数把buf中的数据copy到server的发送缓冲区它就返回了。由于此时c/s连接已经断开,这些数据并没有被发送出去。接着服务器接收下一个指令,并继续调用send函数去响应客户端,由于上次东西没被发送出去,所以就出现了SOCKET_ERROR,并终止了当前进程,从而出现了断开的通道。
解决方法很简单:其实也是本人了解太少了,,如果连接断开recv()函数会返回一个0,我们对其进行处理就行了。
else if(0==recvnum) break;
貌似和send没关,但这个错误却促使我去认真了解了send函数
相关文章推荐
- TCP/IP网络编程 学习笔记_8 --优雅地断开套接字连接
- TCP/IP网络编程 学习笔记_8 --优雅地断开套接字连接
- 关于linux下的udp/tcp通信设置发送sendto/接收recvfrom信息超时的参数。解决通道堵塞问题。
- TCP/IP网络编程 学习笔记_8 --优雅地断开套接字连接
- TCP套接字编程
- tcp套接字编程模型
- 是tcp和udp只和套接字类型有关,和send,recv,connect无关,这些都是协议无关的函数
- 第13章 TCP编程(1)_socket套接字
- 网络 套接字编程 TCP、UDP
- 网络编程与并发-TCP/UDP套接字、粘包问题、Socket编程、并发编程、FTP作业
- linux网络编程之套接字/TCP/IP
- Java TCP套接字编程
- Socket套接字编程(一)——TCP编程
- 【HTTP】TCP连接与套接字编程(socket)理论基础
- 基本TCP套接字编程
- 关于检测TCP连接断开
- 关于网络编程中MTU、TCP、UDP优化配置的一些总结
- 《Unix网络编程》卷一(简介TCP/IP、基础套接字编程)
- TCP/IP“优雅地”打开与断开套接字。
- 关于socket编程中服务器端如何检测客户端连接断开的问题