socket 编程

来源:互联网 发布:apache日志文件在哪 编辑:程序博客网 时间:2024/06/10 23:33

1、一个简单的socket编程实例

客户端代码:

import java.io.*;
import java.net.*;
public class client
{
public static void main(String args[]) throws Exception
{
Socket socket=new Socket(InetAddress.getLocalHost(),5000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=wt.readLine();
out.println("!"+str);
out.flush();
if(str.equals("end"))
{break;}
System.out.println(in.readLine());
}
socket.close();
}
}

服务器端代码:

import java.io.*;
import java.net.*;
public class server
{
public static void main(String args[]) throws IOException
{
ServerSocket server=new ServerSocket(5000);

Socket socket=server.accept();

System.out.println("has built a link....");

BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out=new PrintWriter(socket.getOutputStream());
while(true)
{
String str=in.readLine();
System.out.println("Server"+str);
out.println("has received...");
out.flush();
if(str.equals("end"))
break;
}
out.close();
in.close();
socket.close();
server.close();
}

}


2、ICMP协议   tracerouting程序

转自:http://blog.csdn.net/microtong/article/details/3220463

本程序实现Windows下tracert的功能,程序使用原始套接字发送ICMP回显请求报文,本接收ICMP超时差错报文,和ICMP回显应答报文,得到每一跳的路由器IP地址和往返时间。

  1. //TraceRoute.h
  2. #ifndef _ITRACERT_H_
  3. #define _ITRACERT_H_
  4. #pragma pack(1)
  5. //IP数据报头
  6. typedef struct
  7. {
  8.  unsigned char hdr_len :4;  // length of the header
  9.  unsigned char version :4;  // version of IP
  10.  unsigned char tos;   // type of service
  11.  unsigned short total_len;  // total length of the packet
  12.  unsigned short identifier;  // unique identifier
  13.  unsigned short frag_and_flags; // flags
  14.  unsigned char ttl;   // time to live
  15.  unsigned char protocol;  // protocol (TCP, UDP etc)
  16.  unsigned short checksum;  // IP checksum
  17.  unsigned long sourceIP;  // source IP address
  18.  unsigned long destIP;   // destination IP address
  19. } IP_HEADER;
  20. //ICMP数据报头
  21. typedef struct
  22. {
  23.  BYTE type;  //8位类型
  24.  BYTE code;  //8位代码
  25.  USHORT cksum;  //16位校验和
  26.  USHORT id;   //16位标识符
  27.  USHORT seq;  //16位序列号
  28. } ICMP_HEADER;
  29. //解码结果
  30. typedef struct
  31. {
  32.  USHORT usSeqNo;   //包序列号
  33.  DWORD dwRoundTripTime; //往返时间
  34.  in_addr dwIPaddr;  //对端IP地址
  35. } DECODE_RESULT;
  36. #pragma pack()
  37. //ICMP类型字段
  38. const BYTE ICMP_ECHO_REQUEST = 8; //请求回显
  39. const BYTE ICMP_ECHO_REPLY  = 0; //回显应答
  40. const BYTE ICMP_TIMEOUT   = 11; //传输超时
  41. const DWORD DEF_ICMP_TIMEOUT = 3000; //默认超时时间,单位ms
  42. const int DEF_ICMP_DATA_SIZE = 32; //默认ICMP数据部分长度
  43. const int MAX_ICMP_PACKET_SIZE = 1024; //最大ICMP数据报的大小
  44. const int DEF_MAX_HOP = 30;    //最大跳站数
  45. USHORT GenerateChecksum(USHORT* pBuf, int iSize);
  46. BOOL DecodeIcmpResponse(char* pBuf, int iPacketSize, DECODE_RESULT& stDecodeResult);
  47. #endif // _ITRACERT_H_
  48. //TraceRoute.cpp
  49. /*----------------------------------------------------------
  50. 功能说明:该程序简单实现了Windows操作系统的tracert命令功能,
  51.       可以输出IP报文从本机出发到达目的主机所经过的路由信息。
  52. -----------------------------------------------------------*/
  53. #include <iostream>
  54. #include <iomanip>
  55. #include <winsock2.h>
  56. #include <ws2tcpip.h>
  57. #include <stdio.h>
  58. #include "TraceRoute.h"
  59. #pragma comment(lib,"ws2_32")
  60. using namespace std;
  61. int main(int argc, char* argv[])
  62. {
  63.  //检查命令行参数
  64.  if (argc != 2)
  65.  {
  66.   cerr << "/nUsage: itracert ip_or_hostname/n";
  67.   return -1;
  68.  }
  69.  //初始化winsock2环境
  70.  WSADATA wsa;
  71.  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
  72.  {
  73.   cerr << "/nFailed to initialize the WinSock2 DLL/n"
  74.     << "error code: " << WSAGetLastError() << endl;
  75.   return -1;
  76.  }
  77.  //将命令行参数转换为IP地址
  78.  u_long ulDestIP = inet_addr(argv[1]);
  79.  if (ulDestIP == INADDR_NONE)
  80.  {
  81.   //转换不成功时按域名解析
  82.   hostent* pHostent = gethostbyname(argv[1]);
  83.   if (pHostent)
  84.   {
  85.    ulDestIP = (*(in_addr*)pHostent->h_addr).s_addr;
  86.    //输出屏幕信息
  87.    cout << "/nTracing route to " << argv[1] 
  88.      << " [" << inet_ntoa(*(in_addr*)(&ulDestIP)) << "]"
  89.      << " with a maximum of " << DEF_MAX_HOP << " hops./n" << endl;
  90.   }
  91.   else //解析主机名失败
  92.   {
  93.    cerr << "/nCould not resolve the host name " << argv[1] << '/n'
  94.      << "error code: " << WSAGetLastError() << endl;
  95.    WSACleanup();
  96.    return -1;
  97.   }
  98.  }
  99.  else
  100.  {
  101.   //输出屏幕信息
  102.   cout << "/nTracing route to " << argv[1] 
  103.     << " with a maximum of " << DEF_MAX_HOP << " hops./n" << endl;
  104.  }
  105.  //填充目的Socket地址
  106.  sockaddr_in destSockAddr;
  107.  ZeroMemory(&destSockAddr, sizeof(sockaddr_in));
  108.  destSockAddr.sin_family = AF_INET;
  109.  destSockAddr.sin_addr.s_addr = ulDestIP;
  110.  //使用ICMP协议创建Raw Socket
  111.  SOCKET sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
  112.  if (sockRaw == INVALID_SOCKET)
  113.  {
  114.   cerr << "/nFailed to create a raw socket/n"
  115.     << "error code: " << WSAGetLastError() << endl;
  116.   WSACleanup();
  117.   return -1;
  118.  }
  119.  //设置端口属性
  120.  int iTimeout = DEF_ICMP_TIMEOUT;
  121.  if (setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout)) == SOCKET_ERROR)
  122.  {
  123.   cerr << "/nFailed to set recv timeout/n"
  124.     << "error code: " << WSAGetLastError() << endl;
  125.   closesocket(sockRaw);
  126.   WSACleanup();
  127.   return -1;
  128.  }
  129.  //创建ICMP包发送缓冲区和接收缓冲区
  130.  char IcmpSendBuf[sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE];
  131.  memset(IcmpSendBuf, 0, sizeof(IcmpSendBuf));
  132.  char IcmpRecvBuf[MAX_ICMP_PACKET_SIZE];
  133.  memset(IcmpRecvBuf, 0, sizeof(IcmpRecvBuf));
  134.  //填充待发送的ICMP包
  135.  ICMP_HEADER* pIcmpHeader = (ICMP_HEADER*)IcmpSendBuf;
  136.  pIcmpHeader->type = ICMP_ECHO_REQUEST;
  137.  pIcmpHeader->code = 0;
  138.  pIcmpHeader->id = (USHORT)GetCurrentProcessId();
  139.  memset(IcmpSendBuf+sizeof(ICMP_HEADER), 'E', DEF_ICMP_DATA_SIZE);
  140.  //开始探测路由
  141.  DECODE_RESULT stDecodeResult;
  142.  BOOL bReachDestHost = FALSE;
  143.  USHORT usSeqNo = 0;
  144.  int iTTL = 1;
  145.  int iMaxHop = DEF_MAX_HOP;
  146.  while (!bReachDestHost && iMaxHop--)
  147.  {
  148.   //设置IP数据报头的ttl字段
  149.   setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char*)&iTTL, sizeof(iTTL));
  150.   //输出当前跳站数作为路由信息序号
  151.   cout << setw(3) << iTTL << flush;
  152.   //填充ICMP数据报剩余字段
  153.   ((ICMP_HEADER*)IcmpSendBuf)->cksum = 0;
  154.   ((ICMP_HEADER*)IcmpSendBuf)->seq = htons(usSeqNo++);
  155.   ((ICMP_HEADER*)IcmpSendBuf)->cksum = GenerateChecksum((USHORT*)IcmpSendBuf, sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE);
  156.   
  157.   //记录序列号和当前时间
  158.   stDecodeResult.usSeqNo = ((ICMP_HEADER*)IcmpSendBuf)->seq;
  159.   stDecodeResult.dwRoundTripTime = GetTickCount();
  160.   
  161.   //发送ICMP的EchoRequest数据报
  162.   if (sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), 0, 
  163.        (sockaddr*)&destSockAddr, sizeof(destSockAddr)) == SOCKET_ERROR)
  164.   {
  165.    //如果目的主机不可达则直接退出
  166.    if (WSAGetLastError() == WSAEHOSTUNREACH)
  167.     cout << '/t' << "Destination host unreachable./n" 
  168.       << "/nTrace complete./n" << endl;
  169.    closesocket(sockRaw);
  170.    WSACleanup();
  171.    return 0;
  172.   }
  173.   //接收ICMP的EchoReply数据报
  174.   //因为收到的可能并非程序所期待的数据报,所以需要循环接收直到收到所要数据或超时
  175.   sockaddr_in from;
  176.   int iFromLen = sizeof(from);
  177.   int iReadDataLen;
  178.   while (1)
  179.   {
  180.    //等待数据到达
  181.    iReadDataLen = recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, 
  182.          0, (sockaddr*)&from, &iFromLen);
  183.    if (iReadDataLen != SOCKET_ERROR) //有数据包到达
  184.    {
  185.     //解码得到的数据包,如果解码正确则跳出接收循环发送下一个EchoRequest包
  186.     if (DecodeIcmpResponse(IcmpRecvBuf, iReadDataLen, stDecodeResult))
  187.     {
  188.      if (stDecodeResult.dwIPaddr.s_addr == destSockAddr.sin_addr.s_addr)
  189.       bReachDestHost = TRUE;
  190.      cout << '/t' << inet_ntoa(stDecodeResult.dwIPaddr) << endl;
  191.      break;
  192.     }
  193.    }
  194.    else if (WSAGetLastError() == WSAETIMEDOUT) //接收超时,打印星号
  195.    {
  196.     cout << setw(9) << '*' << '/t' << "Request timed out." << endl;
  197.     break;
  198.    }
  199.    else
  200.    {
  201.     cerr << "/nFailed to call recvfrom/n"
  202.       << "error code: " << WSAGetLastError() << endl;
  203.     closesocket(sockRaw);
  204.     WSACleanup();
  205.     return -1;
  206.    }
  207.   }
  208.   //TTL值加1
  209.   iTTL++;
  210.  }
  211.  //输出屏幕信息
  212.  cout << "/nTrace complete./n" << endl;
  213.  closesocket(sockRaw);
  214.  WSACleanup();
  215.  return 0;
  216. }
  217. //产生网际校验和
  218. USHORT GenerateChecksum(USHORT* pBuf, int iSize) 
  219. {
  220.  unsigned long cksum = 0;
  221.  while (iSize>1) 
  222.  {
  223.   cksum += *pBuf++;
  224.   iSize -= sizeof(USHORT);
  225.  }
  226.  if (iSize) 
  227.   cksum += *(UCHAR*)pBuf;
  228.  cksum = (cksum >> 16) + (cksum & 0xffff);
  229.  cksum += (cksum >> 16);
  230.  return (USHORT)(~cksum);
  231. }
  232. //解码得到的数据报
  233. BOOL DecodeIcmpResponse(char* pBuf, int iPacketSize, DECODE_RESULT& stDecodeResult)
  234. {
  235.  //检查数据报大小的合法性
  236.  IP_HEADER* pIpHdr = (IP_HEADER*)pBuf;
  237.  int iIpHdrLen = pIpHdr->hdr_len * 4;
  238.  if (iPacketSize < (int)(iIpHdrLen+sizeof(ICMP_HEADER)))
  239.   return FALSE;
  240.  //按照ICMP包类型检查id字段和序列号以确定是否是程序应接收的Icmp包
  241.  ICMP_HEADER* pIcmpHdr = (ICMP_HEADER*)(pBuf+iIpHdrLen);
  242.  USHORT usID, usSquNo;
  243.  if (pIcmpHdr->type == ICMP_ECHO_REPLY)
  244.  {
  245.   usID = pIcmpHdr->id;
  246.   usSquNo = pIcmpHdr->seq;
  247.  }
  248.  else if(pIcmpHdr->type == ICMP_TIMEOUT)
  249.  {
  250.   char* pInnerIpHdr = pBuf+iIpHdrLen+sizeof(ICMP_HEADER);  //载荷中的IP头
  251.   int iInnerIPHdrLen = ((IP_HEADER*)pInnerIpHdr)->hdr_len * 4;//载荷中的IP头长
  252.   ICMP_HEADER* pInnerIcmpHdr = (ICMP_HEADER*)(pInnerIpHdr+iInnerIPHdrLen);//载荷中的ICMP头
  253.   usID = pInnerIcmpHdr->id;
  254.   usSquNo = pInnerIcmpHdr->seq;
  255.  }
  256.  else
  257.   return FALSE;
  258.  if (usID != (USHORT)GetCurrentProcessId() || usSquNo !=stDecodeResult.usSeqNo) 
  259.   return FALSE;
  260.  //处理正确收到的ICMP数据报
  261.  if (pIcmpHdr->type == ICMP_ECHO_REPLY ||
  262.   pIcmpHdr->type == ICMP_TIMEOUT)
  263.  {
  264.   //返回解码结果
  265.   stDecodeResult.dwIPaddr.s_addr = pIpHdr->sourceIP;
  266.   stDecodeResult.dwRoundTripTime = GetTickCount()-stDecodeResult.dwRoundTripTime;
  267.   //打印屏幕信息
  268.   if (stDecodeResult.dwRoundTripTime)
  269.    cout << setw(6) << stDecodeResult.dwRoundTripTime << " ms" << flush;
  270.   else
  271.    cout << setw(6) << "<1" << " ms" << flush;
  272.   return TRUE;
  273.  }
  274.  return FALSE;
  275. }

3、和服务器建立TCP连接   SNMP协议监测主机上的这条TCP连接 获取监测的信息


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <Iphlpapi.h>
#include <malloc.h>
#include <Winsock2.h>
#include <stdlib.h>
#include <tchar.h>
#include<windef.h>
LPVOID lpMsgBuf;
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
char receiveMessage[5000]="";
char sendMessage[512]=""; 
static char TcpState[][32] = 
{
"CLOSED",
"LISTENING",
"SYN_SENT",
"SEN_RECEIVED",
"ESTABLISHED",
"FIN_WAIT",
"FIN_WAIT2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
DWORD EnumTCPTable()
{
PMIB_TCPTABLE pTcpTable = NULL;
DWORD dwSize = 0;
DWORD dwRetVal = ERROR_SUCCESS;

struct   in_addr rip;
struct   in_addr lip;
char  szrip[32] = {0};
char  szlip[32] = {0};

//获得pTcpTable所需要的真实长度,dwSize
if (GetTcpTable(pTcpTable, &dwSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
{
pTcpTable = (MIB_TCPTABLE*) malloc ((UINT) dwSize);
}
else
return dwRetVal;

printf("Active Connections\n\n");
printf("  Proto\t%-24s%-24s%s\n","Local Address","Foreign Address","State");

if ((dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE)) == NO_ERROR) 
{
int i;
for (i = 0; i < (int) pTcpTable->dwNumEntries; i++) 
{
rip.S_un.S_addr = pTcpTable->table[i].dwRemoteAddr;
lip.S_un.S_addr = pTcpTable->table[i].dwLocalAddr;
//监听端口,远程主机端口为0,但函数返回是有值的,不知道它是怎么考虑的
if (pTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)   
pTcpTable->table[i].dwRemotePort = 0;

//dwLocalPort,dwRemotePort 是网络字节
//printf("%d\n",pTcpTable->table[i].dwRemotePort);

//注:htons((short)aaaaa)转换成int类型是bbbbb,通过该条件筛出需要的tcp连接
if(pTcpTable->table[i].dwRemotePort==xxxxxx){
_snprintf(szlip,sizeof(szlip),"%s:%d",inet_ntoa(lip),htons((u_short)pTcpTable->table[i].dwLocalPort));
_snprintf(szrip,sizeof(szrip),"%s:%d",inet_ntoa(rip),htons((u_short)pTcpTable->table[i].dwRemotePort));
printf("  TCP\t%-24s%-24s%s\n",szlip,szrip,TcpState[pTcpTable->table[i].dwState]);
_snprintf(sendMessage,sizeof(sendMessage),"Local Address:%s Foreign Address:%s State:%s "hello world!",szlip
,szrip,TcpState[pTcpTable->table[i].dwState]);}
}
}
else
{
printf("\tCall to GetTcpTable failed.\n");

if (FormatMessage( 
FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM | 
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwRetVal,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL ))
{
printf("\tError: %s", lpMsgBuf);
}
LocalFree( lpMsgBuf );
}
GlobalFree(pTcpTable);
return dwRetVal;
}

int main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int ret;
 SOCKET sClient; //连接套接字
 struct sockaddr_in saServer; //地址信息
 char *ptr;
 BOOL fSuccess = TRUE;
  ptr = (char *)&receiveMessage;
 //WinSock初始化
 wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本
 ret = WSAStartup(wVersionRequested, &wsaData);
 if(ret!=0)
 {
  printf("WSAStartup() failed!\n");
  return -1;
 }
 //创建Socket,使用TCP协议
 sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 if (sClient == INVALID_SOCKET)
 {
  WSACleanup();
  printf("socket() failed!\n");
  return;
 }


 //构建服务器地址信息
 saServer.sin_family = AF_INET; //地址家族
 saServer.sin_port = htons((short)端口); //注意转化为网络节序
 saServer.sin_addr.S_un.S_addr = inet_addr("ip地址");


 //连接服务器
 ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
 if (ret == SOCKET_ERROR)
 {
  printf("connect() failed!\n");
  closesocket(sClient); //关闭套接字
  WSACleanup();
  return -1;
 }


//DWORD TcpInfo = EnumTCPTable();
  EnumTCPTable();


ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
 if (ret == SOCKET_ERROR)
 {
  printf("send() failed!\n");
 }
 else
  printf("send message :%s\n",sendMessage);
 
 ret = recv(sClient, ptr, 5000, 0);
   if (ret == SOCKET_ERROR)
   {
    printf("recv() failed!\n");
    return;
   }


   if (ret == 0) //客户端已经关闭连接
   {
    printf("Client has closed the connection\n");
return ;


   }
 printf("receive message:%s\n", receiveMessage);//打印我们接收到的消息。
 closesocket(sClient); //关闭套接字
 WSACleanup();
}