JAAS配置

1.web.xml

  <!-- JAAS认证 -->
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>protected-resource</web-resource-name>
      <url-pattern>*.jsp</url-pattern>
      <url-pattern>*.action</url-pattern>
      <http-method>HEAD</http-method>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
      <http-method>PUT</http-method>
      <http-method>DELETE</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>NEOJAAS</role-name>
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/login.jsp</form-login-page>
      <form-error-page>/error.jsp</form-error-page>
    </form-login-config>
  </login-config>
  <security-role>
    <description>JAASTest Roles</description>
    <role-name>NEOJAAS</role-name>
  </security-role>

2.login.jsp

<form method="post" action="j_security_check"&#93;
  <label>用户名</label>
  <input name="j_username" type="text" maxlength="32" class="login-text"/>
  <label>密&nbsp;&nbsp;&nbsp;码</label>
  <input name="j_password" type="password" maxlength="32" class="login-text"/>
  <input type="submit" class="stuff" value="登&nbsp;录" />
</form>

好书推荐

1.C,CPP
《C++ Primer》当然放到第一位啦,一个词:经典

2.MFC
《深入浅出MFC》这本绝不是快餐,要慢慢品,其中的关键技术方针及图例堪称经典

3.Windows进阶
《Windows核心编程》无论是新手还是老手,都应该好好看的一本书哟

4.Win32汇编
《WINDOWS下32位汇编语言程序设计》初看这部书时,只有一个感觉:这是汇编吗?现在想来,这本书让我对Windows程序的运行原理有了一个较好的认识。虽然是汇编,但看懂不难,呵呵。

5.QT
市面上就没有看到本像样的书,全是垃圾食品。要我说,还没有比QT中的例子更好的资料呢。

6.OpenGL
要看就Google:OpenGL+NeHe

7.Java
《Core Java》两册一定要读!
《Thinking in Java》也不错:)

8.C#
《C#本质论》比某些超级厚的书给力多了

9.设计模式
G4的《Design Pattern》必读经典

10.管理
《人月神话》和《人件》必读经典。

未完待续…

VC计算CString摘要

1、VC计算字符串MD5摘要

//输入:要计算摘要的字符串
//输出:128位MD5摘要
#include <wincrypt.h>
CString szResult;

CString CDigestDlg::CalcMD5(CString strContent)
{
  DWORD dwLength=0;
  BYTE* pbContent=NULL;

  dwLength = (DWORD)strContent.GetLength();
  pbContent = new BYTE[dwLength];
  memcpy(pbContent,strContent.GetBuffer(dwLength),dwLength);

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteMD5[16]; 
  DWORD dwHashLen=16;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteMD5, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteMD5[0],byteMD5[1],byteMD5[2],byteMD5[3],byteMD5[4],byteMD5[5],byteMD5[6],byteMD5[7]
            ,byteMD5[8],byteMD5[9],byteMD5[10],byteMD5[11],byteMD5[12],byteMD5[13],byteMD5[14],byteMD5[15]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

2、VC计算字符串SHA1摘要

//输入:要计算摘要的字符串
//输出:160位SHA1摘要
#include <wincrypt.h>
CString szResult;

CString CDigestDlg::CalcSHA1(CString strContent)
{
  DWORD dwLength=0;
  BYTE* pbContent=NULL;

  dwLength = (DWORD)strContent.GetLength();
  pbContent = new BYTE[dwLength];
  memcpy(pbContent,strContent.GetBuffer(dwLength),dwLength);

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteSHA1[20]; 
  DWORD dwHashLen=20;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteSHA1, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteSHA1[0],byteSHA1[1],byteSHA1[2],byteSHA1[3],byteSHA1[4],byteSHA1[5],byteSHA1[6],byteSHA1[7],
            byteSHA1[8],byteSHA1[9],byteSHA1[10],byteSHA1[11],byteSHA1[12],byteSHA1[13],byteSHA1[14],byteSHA1[15],
            byteSHA1[16],byteSHA1[17],byteSHA1[18],byteSHA1[19]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

VC计算文件摘要

1、VC计算文件MD5摘要

//输入:文件路径
//输出:128位MD5摘要
#include <wincrypt.h>
CString szResult;

CString CMD5AndSHA1Dlg::CalcMD5(CString strFilePath)
{
  //读取文件
  CFile inFile;
  CFileException ex;
  DWORD dwLength=0;
  BYTE* pbContent=NULL;
  BOOL bRet;

  bRet=inFile.Open(strFilePath,CFile::modeRead | CFile::typeBinary | CFile::shareDenyWrite,&ex);
  if(bRet==FALSE)
  {
    return TEXT("Error opening file");;
  }

  dwLength = (DWORD)inFile.GetLength();
  pbContent = new BYTE[dwLength];
  if(pbContent==NULL)
  {
    return TEXT("Error not enough memory");;
  }
  inFile.Read(pbContent,dwLength);
  inFile.Close();

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteMD5[16]; 
  DWORD dwHashLen=16;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteMD5, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteMD5[0],byteMD5[1],byteMD5[2],byteMD5[3],byteMD5[4],byteMD5[5],byteMD5[6],byteMD5[7]
            ,byteMD5[8],byteMD5[9],byteMD5[10],byteMD5[11],byteMD5[12],byteMD5[13],byteMD5[14],byteMD5[15]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

2、VC计算文件SHA1摘要

//输入:文件路径(文件必须小于2^64bit)
//输出:160位SHA1摘要
#include <wincrypt.h>
CString szResult;

CString CMD5AndSHA1Dlg::CalcSHA1(CString strFilePath)
{
  //读取文件
  CFile inFile;
  CFileException ex;
  DWORD dwLength=0;
  BYTE* pbContent=NULL;
  BOOL bRet;

  bRet=inFile.Open(strFilePath,CFile::modeRead | CFile::typeBinary | CFile::shareDenyWrite,&ex);
  if(bRet==FALSE)
  {
    return TEXT("Error opening file");;
  }

  dwLength = (DWORD)inFile.GetLength();
  pbContent = new BYTE[dwLength];
  if(pbContent==NULL)
  {
    return TEXT("Error not enough memory");;
  }
  inFile.Read(pbContent,dwLength);
  inFile.Close();

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteSHA1[20]; 
  DWORD dwHashLen=20;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteSHA1, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteSHA1[0],byteSHA1[1],byteSHA1[2],byteSHA1[3],byteSHA1[4],byteSHA1[5],byteSHA1[6],byteSHA1[7],
            byteSHA1[8],byteSHA1[9],byteSHA1[10],byteSHA1[11],byteSHA1[12],byteSHA1[13],byteSHA1[14],byteSHA1[15],
            byteSHA1[16],byteSHA1[17],byteSHA1[18],byteSHA1[19]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

Tomcat中的Realm

Realm其实就是一个存放用户名,密码及角色的一个“数据库”。
Tomcat中的Realm有下面几种,你也可以使用自己的Realm,只要实现org.apache.catalina.Realm就可以了。

1.JDBCRealm
授权信息存在关系数据库中, 通过JDBC驱动访问
数据库中必须至少有两张表,表示用户及角色
用户表必须至少有两个字段,用户名及密码
角色表必须至少有两个字段,用户名及角色

create table users (
  user_name         varchar(15) not null primary key,
  user_pass         varchar(15) not null
);

create table user_roles (
  user_name         varchar(15) not null,
  role_name         varchar(15) not null,
  primary key (user_name, role_name)
);
<Realm className="org.apache.catalina.realm.JDBCRealm"
  driverName="org.gjt.mm.mysql.Driver"
  connectionURL="jdbc:mysql://localhost/authority?user=dbuser&amp;password=dbpass"
  userTable="users" userNameCol="user_name" userCredCol="user_pass"
  userRoleTable="user_roles" roleNameCol="role_name"/>

2.DataSourceRealm
授权信息存在关系数据库中, 通过JNDI JDBC数据源访问
数据库中必须至少有两张表,表示用户及角色
用户表必须至少有两个字段,用户名及密码
角色表必须至少有两个字段,用户名及角色

create table users (
  user_name         varchar(15) not null primary key,
  user_pass         varchar(15) not null
);

create table user_roles (
  user_name         varchar(15) not null,
  role_name         varchar(15) not null,
  primary key (user_name, role_name)
);
<Realm className="org.apache.catalina.realm.DataSourceRealm"
  dataSourceName="jdbc/authority"
  userTable="users" userNameCol="user_name" userCredCol="user_pass"
  userRoleTable="user_roles" roleNameCol="role_name"/>

3.JNDIRealm
授权信息存在LDAP目录服务器中,通过JNDI提供者访问

<Realm className="org.apache.catalina.realm.JNDIRealm"
  connectionName="cn=Manager,dc=mycompany,dc=com"
  connectionPassword="secret"
  connectionURL="ldap://localhost:389"
  userPassword="userPassword"
  userPattern="uid={0},ou=people,dc=mycompany,dc=com"
  roleBase="ou=groups,dc=mycompany,dc=com"
  roleName="cn"
  roleSearch="(uniqueMember={0})"
/>

4.UserDatabaseRealm
默认配置,只是用于少量用户
授权信息存在用户数据JNDI资源中,该资源通常是一个XML文档 (conf/tomcat-users.xml)

<tomcat-users>
  <user name="tomcat" password="tomcat" roles="tomcat" />
  <user name="role1"  password="tomcat" roles="role1"  />
  <user name="both"   password="tomcat" roles="tomcat,role1" />
</tomcat-users>

5.MemoryRealm
授权信息存在内存中的对象集合中,该对象集合来自XML文档 (conf/tomcat-users.xml).
仅用于测试。

6.JAASRealm
通过JAAS框架访问授权信息,最灵活最开放的一种授权方式。
如果前面几种方式满足不了你的需求,可以先试试这种方式。

<Realm className="org.apache.catalina.realm.JAASRealm"
  appName="MyFooRealm"
  userClassNames="org.foobar.realm.FooUser"
  roleClassNames="org.foobar.realm.FooRole"/>

7.CombinedRealm
采用多种方式授权。

<Realm className="org.apache.catalina.realm.CombinedRealm" >
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
  <Realm className="org.apache.catalina.realm.DataSourceRealm"
    dataSourceName="jdbc/authority"
    userTable="users" userNameCol="user_name" userCredCol="user_pass"
    userRoleTable="user_roles" roleNameCol="role_name"/>
</Realm>

8.LockOutRealm
多次登录失败后,锁定用户

<Realm className="org.apache.catalina.realm.LockOutRealm" >
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
</Realm>

最后,如果你需要加密密码,那么需要只需要在Realm配置中指定所用的摘要算法就可以了

digest="MD5"
digest="SHA"

参考文章

CMD常用命令08特殊符号

1、.
表示当前目录

dir .\

2、..
表示上一级目录

dir ..\

3、””
界定符号,通常用来引用有空格的目录

dir "c:\Documents and settings"

4、::
注释,和REM类似

5、*
通配符号,表示任意个字符

dir c:\windows\*.log

6、?
通配符号,表示任意一个字符

dir c:\?indows

7、^
转义符

echo ^> >d:\1.txt

8、@
只显示命令执行结果

@echo 你好

9、>
重定向符号,覆盖

dir c:\ > d:\test.txt

10、>>
重定向符号,追加

dir c:\ >> d:\test.txt
dir d:\ >> d:\test.txt

11、|
管道符

netstat -an | find "135"

12、,
某些时候可以当空格来使用

echo,
dir,c:\

13、;
当命令相同时,可以将不同目标用来隔离

dir c:\;d:\

14、&
两个命令连续执行

dir c:\ & dir d:\ & dir e:\

15、&&
当&&前的命令执行成功时,执行&&后的命令

dir c:\ && dir d:\
dir z:\ && dir d:\

16、||
当||前的命令执行失败后,才执行||符号后的内容

dir z:\ || dir c:\
dir c:\ || dir d:\

17、%
%%用于引用变量

set hello=hi
echo %hello%

18、:
标签

@echo off
:again
echo It's me again :)
pause
goto again

Mac上安装Wine

Wine可以模拟Windows中的dll调用,从而使Windows程序可以运行在非BSD/UNIX/Linux平台上

1.安装XCode

2.安装MacPorts

3.配置MacPorts
依次执行下面的命令,需要admin授权
配置MacPorts路径

echo export PATH=/opt/local/bin:/opt/local/sbin:\$PATH$'\n'export MANPATH=/opt/local/man:\$MANPATH | sudo tee -a /etc/profile

配置cpu位数

if [ `sysctl -n hw.cpu64bit_capable` -eq 1 ] ; then echo "+universal" | sudo tee -a /opt/local/etc/macports/variants.conf; else echo "not 64bit capable"; fi

4.下载并编译wine

sudo port install wine

5.wine中安装软件

wine $INSTALLER.exe

或者是拷贝exe文件到wine下,但你要自己保证dll文件都在哟
wine的默认目录为

cd ~/.wine/drive_c

6.运行wine中软件

cd ~/.wine/drive_c/Program\ Files/
wine $PROGRAM.exe

7.增加桌面图标
在附件中找到AppleScript编辑器,把下面的东西粘进去

tell application "Terminal"
    do script "/opt/local/bin/wine ~/.wine/drive_c/Program\\ Files/$PATH_TO_PROGRAM.exe"
end tell

编译并运行试一下,如果可以的话,另存为Application
将其拖拽到Dock上就可以啦:)

8.更新Wine

sudo port selfupdate && sudo port upgrade outdated

9.卸载Wine

sudo port uninstall wine
sudo rm -rf /opt ~/.wine /Applications/MacPorts

如果我写的不够仔细,请参考下面的文章:
Installing Wine on Mac OS X

CMD常用命令07Bat截取字符串

%var:~n,k%
把这条命令理解为两条子命令
n为开始截取字符的位置,从左向右位置为(0,1,2,3 ...),从右向左位置为(-1,-2,-3,-4)
k为对n右侧字符截取到的位置,k>0从n向右截取的位置,k<0从字符串尾向前截取的位置
n默认从字符串最左边开始,k默认为截断到字符串尾
@echo off
rem echo %var:~n,k%
set str=0123456789

echo 字符串为:%str%
echo 第一个字符为:%str:~0,1%
echo 第二个字符为:%str:~1,1%
echo 倒数第一个字符为:%str:~-1,1%
echo 倒数第二个字符为:%str:~-2,1%
echo 截取前三个字符:%str:~0,3%
echo 截取后三个字符:%str:~-3,3%
echo 第三个字符及其之后的字符为:%str:~2%
echo 倒数第三个字符及其之后的字符为:%str:~-3%
echo 截取到倒数第三个字符:%str:~0,-3%
echo 截取倒数第五和第四个字符:%str:~-5,2%

pause

函数调用约定

1.STDCALL
微软制定的c语言调用约定,也就是传说中的WINAPI
参数从右向左进行压栈(微软官方文档说从左向右压栈),返回值存在eax中,
被调用函数清理栈,不允许变长参数列表
函数名前增加_,函数名后增加@和参数个数(32位机器上一定被4整除)
ret指令中,有可选参数指定有多少字节需要弹栈

2.CDECL
c语言的默认调用约定
参数从右向左进行压栈,返回值存在eax中,
调用函数清理栈,可用变长参数列表
函数名前会增加_

3.FASTCALL
非跨编译器的c语言调用约定,
前2-3个4字节内的参数被存放到寄存器(edx,eax,ecx)中,其他参数,或大于4字节的参数,按从右到左的顺序被存放在栈中
多数情况下,调用函数负责清理栈
仅适用于参数少,而且实时性要求很高的情况下
函数名前增加@,函数名后增加@和参数个数

4.THISCALL
cpp的调用约定
参数从右向左进行压栈,返回值存在eax中,this指针存在ecx中
每种编译器对函数名称有不同的修饰方法,但基于重载的需要,一般都会增加参数类型和类名
当使用extern “C”的时候,cpp编译器会使用c语言的修饰方法来修饰函数名,这样就可以方便的供别人调用了。

MinGW中Socket基础

1.客户端简单例子
myc.c

#define MINGW32

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef MINGW32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#endif

#define MAXLINE 1024

int main(int argc,char **argv) 
{
  int  sockfd,n;
  char  receline[MAXLINE+1];
  struct  sockaddr_in serveraddr;

  //输入参数太少,退出
  if(argc != 2) 
  { 
    printf("Usage :%s  IP_address\n", argv[0]);
    exit(0);
  }

  #ifdef MINGW32
  //Winsows下启用socket
  WSADATA wsadata;
  if(WSAStartup(MAKEWORD(1,1),&wsadata)==SOCKET_ERROR)
  {
    printf("WSAStartup() fail\n");
    exit(0);
  }
  #endif
  
  //建立socket
  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
    printf("socket() fail\n");
    exit(0);
  }

  //设置协议及Port
  memset(&serveraddr,0,sizeof(serveraddr));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_port=htons(1024);

  //设置IP
  serveraddr.sin_addr.s_addr=inet_addr(argv[1]);

  //连接
  if(connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))==-1)
  {
    printf("connect() fail\n");
    exit(0);
  }

  //读取数据并输入到标准输出
  #ifdef MINGW32
  while((n=recv(sockfd,receline,MAXLINE,0))>0)
  #else
  while((n=read(sockfd,receline,MAXLINE))>0)
  #endif
  { 
    receline[n]=0;
    if(fputs(receline,stdout)==EOF)
    {
      printf("fputs() error\r\n");
    }
  }

  //没有获取数据
  if(n<0) 
  {
    printf("read() fail\n");
  }

  #ifdef MINGW32
  //Winsows下关闭socket
  closesocket(sockfd);
  WSACleanup();
  #endif

  exit(0);
}
&#91;/code&#93;

2.服务端简单例子
mys.c
&#91;code lang="c"&#93;
#define MINGW32

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef MINGW32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#endif

#define LISTENQ 10

int main(int argc,char *argv[])
{
  int  serverfd,connectfd;
  struct  sockaddr_in serveraddr;
  char  buff[1024];
  time_t  tlick;
  int  iRet;

  #ifdef MINGW32
  //Winsows下启用socket
  WSADATA wsadata;
  if(WSAStartup(MAKEWORD(1,1),&wsadata)==SOCKET_ERROR)
  {
    printf("WSAStartup() fail\n");
    exit(0);
  }
  #endif

  //新建socket
  printf("socket()\n");
  serverfd=socket(AF_INET,SOCK_STREAM,0);
  if(serverfd==-1)
  {
    printf("socket() fail\n");
    exit(0);
  }

  //清零
  memset(&serveraddr,0,sizeof(serveraddr));

  //设置协议
  serveraddr.sin_family=AF_INET;
  //设置IP
  serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  //设置Port
  serveraddr.sin_port=htons(1024);

  //绑定端口,监听1024端口的任何请求
  printf("bind()\n");
  iRet=bind(serverfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
  if(iRet==-1)
  {
    printf("bind() fail\n");
    exit(0);
  }

  //监听端口,最大并发数10
  printf("listen()\n");
  iRet=listen(serverfd,LISTENQ);
  if(iRet==-1)
  {
    printf("listen() fail\n");
    exit(0);
  }

  //接受请求,发送主机时间
  for(;;)
  {
    printf("Waiting for connection...\n");
    //接受请求
    connectfd=accept(serverfd,(struct sockaddr*)NULL,NULL);
    //获取时间    
    tlick=time(NULL);
    //格式化时间    
    snprintf(buff,sizeof(buff),"From mys:\n%s",ctime(&tlick));
    //写入时间
    //关闭请求
    #ifdef MINGW32
    send(connectfd,buff,strlen(buff),0);
    closesocket(connectfd);
    #else
    write(connectfd,buff,strlen(buff));
    close(connectfd);
    #endif
  }

  #ifdef MINGW32
  //Winsows下关闭socket
  closesocket(serverfd);
  WSACleanup();
  #endif

  //退出
  exit(0);
}

3.Makefile

all:mys myc

mys:mys.c
	gcc -g -o mys mys.c -l wsock32

myc:myc.c
	gcc -g -o myc myc.c -l wsock32

clean:
	del *~ *.o *.exe