原始套接字实现
来源:互联网 发布:video.js怎么播放flv 编辑:程序博客网 时间:2024/04/30 09:48
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
-
- #ifdef WIN32
- #include <Winsock2.h>
- #include <ws2ipdef.h>
- #include <WS2tcpip.h>
- #else
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #endif
-
- #ifdef WIN32
- #pragma comment(lib,"ws2_32.lib")
- #else
- #define SOCKET_ERROR -1
- typedef int BOOL;
- #endif
-
-
-
- #define DEFAULT_PORT 10089
-
-
- typedef struct ip_head
- {
- union
- {
- unsigned char Version;
- unsigned char HeadLen;
- };
- unsigned char ServiceType;
- unsigned short TotalLen;
- unsigned short Identifier;
- union
- {
- unsigned short Flags;
- unsigned short FragOffset;
- };
- unsigned char TimeToLive;
- unsigned char Protocol;
- unsigned short HeadChecksum;
- unsigned int SourceAddr;
- unsigned int DestinAddr;
- }IP_HEADER;
-
-
-
-
-
-
- typedef struct tcp_head {
- u_short th_sport;
- u_short th_dport;
- unsigned int th_seq;
- unsigned int th_ack;
- unsigned char th_lenres;
- u_char th_flags;
- u_short th_win;
- u_short th_sum;
- u_short th_urp;
- }TCP_HEADER;
-
-
- typedef struct psd_hdr
- {
- unsigned long saddr;
- unsigned long daddr;
- char mbz;
- char ptcl;
- unsigned short tcpl;
- }PSD_HEADER;
-
- typedef struct udp_head
- {
- unsigned short uh_sport;
- unsigned short uh_dport;
- unsigned short uh_len;
- unsigned short uh_sum;
- }UDP_HEADER;
-
- struct tcpiphdr
- {
- ip_head ipHead;
- tcp_head tcpHead;
- };
-
- void InitSocket()
- {
- #ifdef WIN32
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(2, 2);
- int err = WSAStartup(wVersionRequested, &wsaData);
- if(err != 0)
- {
- printf("windows socket DLL initiates faild\n");
- exit(-1);
- }
- #endif
- }
-
-
- int GetErrNo()
- {
- #ifdef WIN32
- return WSAGetLastError();
- #else
- return errno;
- #endif
- }
-
- const char* GetErrStr(int errnum)
- {
- #ifdef WIN32
- return "请查看msdn帮助文档或定义winerror.h";
- #else
- return strerror(errnum);
- #endif
- }
-
- void SetVirtualIp(int fd, const char* userIp)
- {
- bool flag = true;
- if(setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(char *) &flag,sizeof(flag))==SOCKET_ERROR)
- {
- printf("windows socket DLL initiates faild\n");
- exit(-1);
- }
- }
-
- unsigned short CheckSum(unsigned short *buffer, int size)
- {
- unsigned long cksum = 0;
- while(size > 0)
- {
- cksum += *buffer;
- size -= sizeof(unsigned short );
- }
- if (size)
- {
- cksum += *(unsigned short*)buffer;
- }
- cksum = (cksum >> 16) + (cksum & 0xffff);
- cksum += (cksum >> 16);
- return (unsigned short )(~cksum);
- }
-
- void WriteTcpPkg(const char* sourceIp, const char* destIp, unsigned int destPort, char* szBuffer )
- {
- int iTotalSize = sizeof(ip_head) + sizeof(tcp_head);
- int iIpVersion = 4;
- int iIpSize = sizeof(ip_head)/sizeof(unsigned long);
- ip_head ipHead;
- tcp_head tcpHead;
- psd_hdr psdHead;
-
- ipHead.Version = (iIpVersion << 4) | iIpSize;
-
- ipHead.TotalLen = htons(iTotalSize);
- ipHead.Identifier = 1;
- ipHead.FragOffset = 0;
- ipHead.TimeToLive = 128;
- ipHead.Protocol = IPPROTO_TCP;
- ipHead.HeadChecksum = 0;
- ipHead.SourceAddr = inet_addr(sourceIp);
- ipHead.DestinAddr = inet_addr(destIp);
-
- tcpHead.th_sport = htons(DEFAULT_PORT);
- tcpHead.th_dport = htons(destPort);
- tcpHead.th_seq = htonl(0x12345678);
- tcpHead.th_ack = 0;
- tcpHead.th_lenres = (sizeof(tcp_head)/4 << 4 | 0);
- tcpHead.th_flags = 2;
- tcpHead.th_win = htons(512);
- tcpHead.th_urp = 0;
- tcpHead.th_sum = 0;
-
- psdHead.saddr = ipHead.SourceAddr;
- psdHead.daddr = ipHead.DestinAddr;
- psdHead.mbz = 0;
- psdHead.ptcl = IPPROTO_TCP;
- psdHead.tcpl = htons(sizeof(tcp_head));
-
-
- memcpy(szBuffer, &psdHead, sizeof(psdHead));
- memcpy(szBuffer + sizeof(psdHead), &tcpHead, sizeof(tcpHead));
- tcpHead.th_sum = CheckSum( (unsigned short*)szBuffer, sizeof(psdHead) + sizeof(tcpHead));
-
-
- memcpy(szBuffer, &ipHead, sizeof(ipHead));
- memcpy(szBuffer + sizeof(ipHead), &tcpHead, sizeof(tcpHead));
- memset(szBuffer + sizeof(ipHead) + sizeof(tcpHead), 0, sizeof(int));
- ipHead.HeadChecksum = CheckSum((unsigned short*)szBuffer, sizeof(ipHead) + sizeof(tcpHead));
-
- memcpy(szBuffer, &ipHead, sizeof(ipHead));
- }
-
-
-
- void MyConnectTcp(sockaddr_in &servaddr)
- {
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- int r = connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
- int ret = sendto(fd, "hello", 5, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
- struct sockaddr_in clientaddr;
- socklen_t size = sizeof(clientaddr);
- char szBuf[1024];
- ret = recvfrom(fd, szBuf, 1024, 0,(struct sockaddr*)&clientaddr, &size);
- }
-
- int main(int argc, char** argv)
- {
- if(argc < 5)
- {
- printf("usage : tm_client servIp servPort data userIp\n");
- exit(-1);
- }
- char servIp[64], userIp[64], workfId[16];
- int port = atoi(argv[2]);
- strcpy(servIp, argv[1]);
- strcpy(workfId, argv[3]);
- strcpy(userIp, argv[4]);
- struct sockaddr_in servaddr;
-
- InitSocket();
-
-
- int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- if( fd == SOCKET_ERROR)
- {
- printf("%s\n", GetErrStr(GetErrNo()));
- printf("socket函数执行失败\n");
- return 1;
- }
-
-
- BOOL flag = true;
- if(setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR)
- {
- printf("%d", GetErrNo());
- printf("set socket IP_HDRINCL faild\n");
- exit(-1);
- }
-
-
- int nTimeOver = 1000;
- if(setsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&nTimeOver,sizeof(nTimeOver))==SOCKET_ERROR)
- {
- printf("%d", GetErrNo());
- printf("set socket SO_SNDTIMEO faild\n");
- exit(-1);
- }
-
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = inet_addr(servIp);
- servaddr.sin_port = htons(port);
-
-
- char szDataBuf[1024];
-
- memset(szDataBuf, 0, sizeof(szDataBuf));
-
- int ipsize = sizeof(ip_head), tcpsize = sizeof(tcp_head);
- int iTotalSize = sizeof(ip_head) + sizeof(tcp_head);
- WriteTcpPkg(userIp, servIp, port, szDataBuf);
-
-
- if(sendto(fd, szDataBuf, iTotalSize, 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) == SOCKET_ERROR)
- {
- printf("sendto message faild, errno = %d\n", GetErrNo());
- exit(-1);
- }
-
-
- struct sockaddr_in cliaddr;
- socklen_t cliLen = sizeof(cliaddr);
-
- if( recvfrom(fd,szDataBuf, sizeof(iTotalSize), 0, (struct sockaddr*)&cliaddr, &cliLen) < 0)
- {
- printf("recvfrom message faild\n");
- exit(-1);
- }
-
- #ifdef WIN32
- closesocket(fd);
- WSACleanup();
- #else
- close(fd);
- #endif
- return 0;
- }