小弟刚学,tcp/ip 第二次连接时自动关闭,不解啊!!!
因为只能贴10000个字符,大家有明白怎么回事的,可以让我在贴出剩下代码。
小弟刚学tcp/ip,这段程序在第一次客户端连接请求时,一切正常,手动关闭第一次连接,第二次在连接上自动将返回的sock标识置为0,不解啊。。。。。。。。。
//// main.c// unixwork//// Created by huaiyun Yan on 12-8-29.// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.//#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>#include <sybfront.h> //freetds头文件 #include <sybdb.h> //freetds #include "Utility.h"#include <time.h>#define debug#include "list.h"#include "Log.c"#include "Server.h"int main(void){ pthread_mutex_init(&mutex, NULL); LOG("SOCKET:%s", "start log"); int sock_fd, new_fd; // 侦听sock_fd, 新连接new_fd struct sockaddr_in server_addr; // server address information struct sockaddr_in client_addr; // connector's address information socklen_t sin_size;//accept 第三个参数, sizeof(sockaddr_in) int yes = 1;//setsockopt 第四个参数 char* buf; buf = malloc(sizeof(char)*5000); char* delbuf = buf; int ret; tem = 0; int i=10000;//缓冲区大小 //创建侦听Socket if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { //perror("Create listening socket error!"); LOG("SOCKET:%s", "socket函数调用失败!"); exit(1); } //配置侦听Socket //closesocket后想继续重用该socket。(一般不会立即关闭而经历TIME_WAIT的过程) if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { LOG("SOCKET:%s", "setsockopt函数调用失败!"); exit(1); } setsockopt(sock_fd,SOL_SOCKET,SO_RCVBUF,&i,sizeof(int)); setsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,&i,sizeof(int)); server_addr.sin_family = AF_INET; // host byte order server_addr.sin_port = htons(MYPORT); // short, network byte order server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));//? //绑定新创建的Socket到指定的IP和端口 if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { LOG("SOCKET:%s", "bind函数调用失败!"); exit(1); } //开始侦听,最大连接数为BACKLOG if (listen(sock_fd, BACKLOG) == -1) { LOG("SOCKET:%s", "listen函数调用失败!"); exit(1); } LOG("SOCKET:listen port %d!", MYPORT); //监控文件描述符集合 fd_set fdsr; //监控文件描述符集合中最大的文件号 int maxsock; //Select超时返回的时间。 struct timeval tv; conn_amount = 0; sin_size = sizeof(client_addr); maxsock = sock_fd; while (1) { // 初始化文件描述符集合 FD_ZERO(&fdsr); // 把主机Sock_fd加入到文件描述符集合 FD_SET(sock_fd, &fdsr); // 超时设置30秒 tv.tv_sec = 10; tv.tv_usec = 0; //if(conn_head != NULL) // int j = length(conn_head); // 客户端socket句柄加入文件描述符集合 node_t* huodong_conn_head = conn_head; while( huodong_conn_head != NULL ) { int tem_huodong_conn_head = atoi(huodong_conn_head->data); LOG("tem_huodong_conn_head:%i", tem_huodong_conn_head); if ( tem_huodong_conn_head != 0) { FD_SET(tem_huodong_conn_head, &fdsr); } huodong_conn_head = huodong_conn_head->next; } //Select 函数原型 //int select(nfds, readfds, writefds, exceptfds, timeout) //nfds: select监视的文件句柄数,视进程中打开的文件数而定,一般设为呢要监视各文件中的 //最大文件号加一 //readfds:select监视的可读文件句柄集合 //writefds:select监视的可写文件句柄集合。 //exceptfds:select监视的异常文件句柄集合。 //timeout:本次select的超时结束时间。 ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv); if (ret < 0) { LOG("SOCKET:%s","select error!"); break; } else if (ret == 0) { LOG("SOCKET:%s","timeout!"); // 检查不正常连接并关闭 node_t* tem_close_conn_head = conn_head; while( tem_close_conn_head != NULL ) { myTem = atoi(tem_close_conn_head->data); if ( myTem != 0) { int len_close; char* tem_close_Buf; tem_close_Buf = "a"; len_close = send(myTem ,tem_close_Buf,2,0); if(len_close <= 0)//客户端已经不存在,删除 { del_node( &conn_head, del_condition ); close(myTem); conn_amount--; //重新赋值临时链表指针,防止新指针节点删除后,旧指针记录原有地址 tem_close_conn_head = conn_head; LOG("SOCKET:Client Close,剩余客户端数:[%d]",conn_amount); } }else { del_node( &conn_head, del_condition ); close(myTem); conn_amount--; //重新赋值临时链表指针,防止新指针节点删除后,旧指针记录原有地址 tem_close_conn_head = conn_head; LOG("SOCKET:Client Close,myTem = 0,剩余客户端数:[%d]",conn_amount); } tem_close_conn_head = tem_close_conn_head->next; } continue; } // 检查主机是否有新的客户端连接到来 if (FD_ISSET(sock_fd, &fdsr)) { //接受连接 new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); if (new_fd <= 0) { LOG("SOCKET:%s","accept socket error!"); continue; } // 将新的连接加入到监控文件描述符集合 if (conn_amount < BACKLOG) { //fd_A[conn_amount++] = new_fd; //转换为char保存 char* connFD; connFD = malloc(sizeof(char)*20); memset(connFD,0,sizeof(char)*20); sprintf(connFD,"%i",new_fd); insert_node( &conn_head, connFD, sizeof(char)*20); conn_amount++; LOG("SOCKET:New Connection client,现有客户端数:[%d] %s:%d",conn_amount,inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); //返回给客户端连接成功 sendClientConnOK(new_fd); if (new_fd > maxsock) maxsock = new_fd; } else { LOG("SOCKET:%s","Max connections arrive, exit"); close(new_fd); continue; } } // 轮询各个文件描述符(socket) node_t* tem_allold_conn_head = conn_head; while( tem_allold_conn_head != NULL) { tem = atoi(tem_allold_conn_head->data); if ( tem != 0) { // >0表示可读写。 if (FD_ISSET(tem, &fdsr)) { memset(buf,0,sizeof(char)*5000); //接收数据 ret = recv(tem, buf, sizeof(char)*5000, 0); if (ret <= 0) //接收数据出错 { del_node( &conn_head, del_con_Zc ); close(tem); conn_amount--; //重新赋值临时链表指针,防止新指针节点删除后,旧指针记录原有地址 tem_allold_conn_head = conn_head; LOG("SOCKET:Client Close,剩余客户端数:[%d] %s:%d",conn_amount,inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); break; } else // 数据接收成功 { if (ret < BUF_SIZE) { struct InComment* inComm; struct InNew* inNew; struct LoginCheck* myLoginCheck; node_t* tempNewAndCommend; //获取数据包头 struct HEADER_S* pstHeader; pstHeader = malloc(sizeof(struct HEADER_S)); memset(pstHeader,0,sizeof(struct HEADER_S)); ReadHdrFromBuf(buf,pstHeader); //解析包头,响应客户端请求 switch(pstHeader->usPacketType) { case TYPE_SHOUYE_DATA: //根据请求的包序号发送 sendData(tem, pstHeader->usPacketCurrNum, shouYeBook, TYPE_SHOUYE_DATA); break; defalut: break; } break; } } } else { LOG("SOCKET:%s!", "lun xuan no data!"); } } //判断是否被删除 if(tem_allold_conn_head != NULL) tem_allold_conn_head = tem_allold_conn_head->next; } } exit(0);}