当前位置:文档之家› MFC网络编程技巧

MFC网络编程技巧

MFC网络编程技巧
MFC网络编程技巧

Socket编程技巧

(一)Socket编程的重要数据结构

1、网络字节顺序与主机字节顺序

两种主机字节顺序:低位先存,高位先存(根据机器的不同和有区别,目前的INTER主机为低位先存方式)

网络字节顺序:对于16位或32位整数TCP/IP要求高位先存

相关转换函数:

htons()--"Host to Network Short";

htonl()--"Host to Network Long";

ntohs()--"Network to Host Short";

ntohl()--"Network to Host Long";

2、地址结构

(1)struct sockaddr //套接字地址结构

{

unsigned short sa_family; //internet协议族AF_INET

char sa_data[14]; //14字节的协议地址,包括IP地址和端口

};

(2)struct sockaddr_in //in 代表internet

{

short int sin_family; //internet协议族=AF_INET,IPV4; =AF_INET6, IPV6

unsigned short int sin_port; //端口号,必须是网络字节顺序调用htons()函数

struct in_addr sin_addr; //internet地址,必须是网络字节顺序调用htonl()函数

unsigned char sin_zero[8] //填0

};

(3)struct in_addr //IPv4地址,4个字节

{

unsigned long s_addr;

};

(二)Socket编程中几个重要的函数

(1)socket():套接字创建—指定协议一元

int socket(int domain,int type,int protocal)

int domain, //通信域AF_INET—internet域;AF_UNIX—UNIX域

int type, //指定socket的类型:SOCK_STREAM(流式套接字,TCP),SOCK_DGRAM(数据报套接字,UDP),SOCK_RAW(原始数据报套接字)

int protocol //指定网络协议,0表示由系统选择合适协议,默认TCP/IP协议

返回值:成功---整型socket号sockfd ,失败--- -1

例子:socket(AF_INET, SOCK_STREAM,0)

socket(AF_INET, SOCK_ DGRAM ,0)

(2)bind():命名套接字---指定本地二元,绑定套接字号

int bind(int sockfd,struct sockaddr *my_addr,int addrlen)

int sockfd, //socket描述符

struct sockaddr *my_addr, //指向包含有本机IP地址及端口号等信息的sockaddr类型的指针

int addrlen, //sizeof(struct sockaddr)

返回值:成功----0; 失败---- <0,SOCKET_ERROR错误

作用:将套接字地址与套接字号关联----指点了三元组套接字标识

例子:bind(18, my_addr, sizeof(struct sockaddr))

my_addr.sin_port= htonl (2222); // =0,系统随机设定1024~5000;自己设定,应选>1024

my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//允许服务器应用进程侦听每个网络接口上的客户机请求.

(3)listen():监听连接---服务程序监听连接请求,并进行排队,供accept进行后续处理.

int listen(int sockfd,int backlog)

int sockfd, //服务器通过该套接字侦听客户请求

int backlog //请求队列长度,超过长度,服务器拒绝连接请求

返回值:0--成功,-1--失败

(4)accept()允许服务器通过套接字接收一个连接请求—服务程序使用

作用:从listen队列取出第一个连接请求,创建一新的套接字,准备提供并发服务.

int accept(ing sockfd,struct sockaddr *addr,int *addrlen)

int sockfd, //被监听的socket号,服务器从该套接字接收connect请求

struct sockaddr * addr, //存放提出连接请求服务的客户机套接字地址

int *addrlen //客户机套接字地址addr长度,sizeof(sockaddr)

返回值:若成功建立一个连接,返回的是一个新的socekt号,供新的连接使用;父进程则通过以前的套接字继续接收客户请求. -1--失败

(5)connect():请求与远程套接字连接---客户程序使用

int connect(int sockfd,struct sockaddr *serv_addr,int addrlen)

int sockfd, //本地套接字号

struct sockaddr *serv_addr, //serv_addr包含服务器IP地址和端口号地址结构的指针

int addrlen //serv_addr的长度,sizeof(sockaddr)

返回:0---成功,-1---失败

connect()与accept()建立一个全相关五元组

(6)send():发送数据

int send(int sockfd,const void *msg,int len,int flags)

int sockfd, //已连接的用来传输数据的套接字号

const void *msg, //指向要发送数据缓冲区的指针

int len, //以字节为单位的数据的长度

int flags //指定传输控制方式,一般情况下置为0,MSG_OOB,(发送TCP紧急带外数据)

返回值:实际发送的数据长度,可能少于len(7)接收数据

(7)recv():接受数据

int recv(int sockfd,void *buf,int len,unsigned int flags)

int sockfd, //接受数据的套接字号

void *buf, //存放接收数据的缓冲区指针

int len, //缓冲区的长度

unsigned int flags //调用方式.一般情况下置为0,MSG_OOB:读取套接字上的紧急带外数据,MSG_PEEK:仅查看数据,不取出

返回:0----连接被关闭,>0接收的总字节数,<0 SOCKET_ERROR

(8)sendto():UDP—发送数据

int sendto(int sockfd,const void *msg,int len,unsigned int flags,const struct sockaddr *to,int tolen)

int sockfd,

const void * msg, //指向要发送数据的指针

int len, //以字节为单位的数据的长度

unsigned int flags, //flags一般情况下置为0

const struct sockaddr * to, //存放目的机套接字地址

int tolen // sizeof(sockaddr)

返回值:实际发送的数据长度,可能少于len

(9)recvfrom():UDP—接收数据

int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen)

int sockfd,

void * buf, //存放接收数据的缓冲区指针

int len, //缓冲区的长度

unsigned int flags //flags一般情况下置为0

struct sockaddr *from, //存保发送来数据的源机的套接字地址

int *fromlen //sizeof(formlen)

返回值:收到的数据长度,如果=-1 出错

(10)关闭套接字

int close(int sockfd); //关闭指定的socket。

返回:0--关闭成功,SOCKET_ERROR--错误

(11)通知关闭套接字

int shutdown(int sockfd,int how)

直接用close关闭套接字,可能会导致数据丢失.在close前,应调用shutdown发送给对方关闭通知,shutdown并不关闭套接字,套接字所占资源将保留到close套接字时.

参数how可以设为下列值:

0:不允许继续接收数据

1:不允许继续发送数据

2:不允许继续发送和接收数据

返回值:成功---0,出错--- SOCKET_ERROR

(12)辅助socket函数:

int getsockname(int sockfg,struct sockaddr* addr, int *addrlen)

int getpeername(int sockfd, struct sockaddr* addr, int *addrlen);

int getsockopt(int sockfd,int level,int optname, void* optval, int * optlen);

int setsockopt(int sockfd,int level,int optname, const void* optval,int optlen)

unsigned long inet_addr(const char *strptr);

int inet_aton(const char *strptr, struct in_addr *addrpt);

char *inet_ntoa(struct in_addr inaddr);

int ioctl(int fd, int request, …/*void *arg*/)

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

(13)域名与IP转换函数,服务与端口号转换函数。

struct hostent *gethostbyname(const char *name);

struct hostent

{

char *h_name; //https://www.doczj.com/doc/f310921501.html,

char **h_aliases; //https://www.doczj.com/doc/f310921501.html,

int h_addrtype; //2, AF_INET

int h_length; // 4

char **h_addr_list;

}

struct hostent *gethostbyaddr(const char *addr,int len,int family); int gethostname(char *name, int namelen);

第二部分:一个简单的客户端程序

#include

#include

#define PORT (u_short) 1080

#define SERVER_ADDR "202.96.1.144"

int main(void)

{

WSADATA Data;

SOCKET sServer;

SOCKET sClient;

char buffer[MAXBUFLEN];

int status;

int ret;

SOCKADDR_IN serverSockAddr;

int addrLen = sizeof(sockaddr_in);

char *toSendtxt="Test String..";

/* initialize the Windows Socket DLL */

status = WSAStartup(MAKEWORD(2, 2), &Data);

if (status != 0)

{

cout << "ERROR: WSAStartup unsuccessful" << endl;

return 1;

}

/* create a socket */

sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INV ALID_SOCKET)

{

cout << "ERROR: socket unsuccessful" << endl;

status = WSACleanup();

if (status == SOCKET_ERROR)

{

cout << "ERROR: WSACleanup unsuccessful" << endl;

return 2;

}

return 3;

}

serverSockAddr.sin_family = AF_INET;

serverSockAddr.sin_port = htons(PORT);

serverSockAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);

cout << "Trying to connect to IP Address: " << SERVER_ADDR << endl;

/* connect to the server */

status = connect(sClient, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr)); if (status == SOCKET_ERROR)

{

cout << "ERROR: connect unsuccessful" << endl;

status=closesocket(sClient);

if (status == SOCKET_ERROR)

{

cout << "ERROR: closesocket unsuccessful" << endl;

return 4;

}

status=WSACleanup();

if (status == SOCKET_ERROR)

{

cout << "ERROR: WSACleanup unsuccessful"<< endl;

return 5;

}

return 6;

}

cout << "Connected..." << endl;

while(1)

{

cout << "Sending..." << endl;

ret = send(sClient, toSendtxt, strlen(toSendtxt) + 1, 0);

if (ret != (int)strlen(toSendtxt) + 1)

{

cout << "Connection terminated" << endl;

status = closesocket(sClient);

if (status == SOCKET_ERROR)

{

cout << "ERROR: closesocket unsuccessful" << endl;

return 7;

}

status = WSACleanup();

if (status == SOCKET_ERROR)

{

cout << "ERROR: WSACleanup unsuccessful" << endl;

return 8;

}

return 9;

}

/* Wait before sending the message again */

Sleep(4800);

}

}

第三部分:一个简单的服务器程序

#include

#include

#include

#include

using namespace std;

#define PORT (u_short) 1080

#define SERVER_ADDR "202.96.1.144"

#define MAXBUFLEN 100

int main(void)

{

WSADATA Data;

SOCKADDR_IN serverSockAddr;

SOCKADDR_IN clientSockAddr;

SOCKET sServer;

SOCKET sClient;

int addrLen = sizeof(SOCKADDR_IN);

int status, ret;

int i = 1;

const string end = "..";

char buffer[MAXBUFLEN];

bool flag = false;

/* initialize the Windows Socket DLL */

status = WSAStartup(MAKEWORD(2, 2), &Data);

if (status != 0)

{

cout << "ERROR: WSAStartup unsuccessful" << endl; return 1;

}

/* zero the sockaddr_in structure */

memset(&serverSockAddr, 0, sizeof(serverSockAddr));

serverSockAddr.sin_port=htons(PORT);

serverSockAddr.sin_family=AF_INET;

serverSockAddr.sin_addr.s_addr=inet_addr(SERVER_ADDR);

/* create a socket */

sServer = socket(AF_INET, SOCK_STREAM, 0);

if (sServer == INV ALID_SOCKET)

{

cout << "ERROR: socket unsuccessful" << endl;

return 2;

}

/* associate the socket with the address */

status = bind(sServer, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr)); if (status == SOCKET_ERROR)

{

cout << "ERROR: bind unsuccessful" << endl;

return 3;

}

/* allow the socket to take connections */

status = listen(sServer, 1);

if (status == SOCKET_ERROR)

{

cout << "ERROR: listen unsuccessful" << endl;

return 4;

}

cout << "Waiting for the connection..." << endl;

/* accept the connection request when one is received */

sClient = accept(sServer, (struct sockaddr *)&clientSockAddr, &addrLen);

cout << "Got the connection..." << endl;

while(1)

{

ret = recv(sClient, buffer, MAXBUFLEN, 0);

const char *p_end = search(buffer, buffer+ret, end.begin(), end.end());

if(p_end != buffer+ret)

flag = true;

if ((ret == 0) || (ret == SOCKET_ERROR))

{

cout << "Connection terminated." << endl;

status = closesocket(sClient);

if (status == SOCKET_ERROR)

{

cout << "ERROR: closesocket unsuccessful" << endl;

return 5;

}

status = closesocket(sServer);

if (status == SOCKET_ERROR)

{

cout << "ERROR: closesocket unsuccessful" << endl;

return 6;

}

status = WSACleanup();

if (status == SOCKET_ERROR)

{

cout << "ERROR: WSACleanup unsuccessful" << endl;

return 7;

}

return 8;

}

cout << buffer;

if(flag)

{

cout <

cout << i << " OVER" << endl;

cout << "...." << endl;

cout << "...." << endl;

i++;

flag = false;

}

/* the times of cout */

if(i>=10)

return 0;

}

}

/********************************************/

/* POST提交数据

/* by xicao from SEU

/* post.c */

/********************************************/

#include

#include

#include

#pragma comment(lib,"ws2_32.lib")

int InitSocket();

u_long Name2Inet(char* szAddress);

int main(int argc,char *argv[])

{

char buff[1024];

SOCKET sock;

SOCKADDR_IN addr;

int postlen;

char* url="127.0.0.1";//这个自己修改

if (argc!=3)

{

printf("Error!\n");

return 0;

}

postlen=(strlen(argv[1])+strlen(argv[2])+19);

_snprintf(buff, 4096, "POST http://%s/pass.asp HTTP/1.1\r\n"

// "Accept: */*\r\n"

"Content-Type: application/x-www-form-urlencoded\r\n" //貌似这句不能丢"Host: %s\r\n"

"Content-Length: %d\r\n" //指post的数据长度

"\r\n"

"QQNumber=%s&PassWord=%s\r\n",

url,

url,

postlen,

argv[1],

argv[2]);

if(!InitSocket())

{

printf("Winsock Initialization failed.\n");

return 0;

}

if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)

{

printf("Can not create socket.\n");

return 0;

}

addr.sin_family = AF_INET;

addr.sin_port = htons(80);

addr.sin_addr.s_addr=Name2Inet(url);

if (connect(sock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR) {

printf("Can not connect to specified host.\n"); return -1;

}

send(sock,buff,strlen(buff),0);

closesocket(sock);

return 0;

}

int InitSocket()

{

#define MAJOR_VERSION 1

#define MINOR_VERSION 2

int nStatus = 0;

WORD wMajorVersion = MAJOR_VERSION;

WORD wMinorVersion = MINOR_VERSION;

WORD wVersionReqd = MAKEWORD(wMajorVersion, wMinorVersion); WSADATA lpmyWSAData;

nStatus =WSAStartup(wVersionReqd, &lpmyWSAData);

if(nStatus != 0)

{

return 0;

}

return 1;

}

u_long Name2Inet(char* szAddress)

{

int name=0;

int i=0;

if(szAddress==NULL||strlen(szAddress)<1)

{

return htonl(INADDR_ANY);

}

for (i=0;szAddress;i++)

{

if((!isdigit(szAddress))&&szAddress!='.') {

name=1;break;

}

}

//不是计算机名,是IP

if(!name)

return inet_addr(szAddress);

//是计算机名

else

{

struct hostent*host=gethostbyname(szAddress);

if(host==NULL)

{

return htonl(INADDR_ANY);

}

return *(long*)host->h_addr;

}

}

1 //TCP Port Check program in windows

2

3

4 #include

5 #include

6

7 #pragma comment(lib,"ws2_32.lib")

8

9

10 int main(int argc, char *argv[])

11 {

12 SOCKET sockfd;

13 SOCKADDR_IN sockaddr;

14 int port;

15 unsigned long ip;

16 WSADATA wsa;

17 int timeout=2,ret;

18 struct timeval tv;

19 struct fd_set fs;

20 unsigned long ul = 1;

21

22

23 if(argc != 4)

24 {

25 printf("Usage: %s IP Port TimeOut\n",argv[0]);

26 return -1;

27 }

28 if((ip=inet_addr(argv[1]))==INADDR_NONE)

29 {

30 printf("IP Address Error\n");

31 return -1;

32 }

33 if((port=atoi(argv[2]))==0)

34 {

35 printf("Port Error\n");

36 return -1;

37 }

38 if((timeout=atoi(argv[3]))==0)

39 {

40 printf("Timeout Error\n");

41 return -1;

42 }

43 WSAStartup(MAKEWORD(1,1),&wsa); //initialize Ws2_32.dll

44

45 if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0) //create a tcp socket

46 {

47 printf("Create socket fail!\n");

48 return -2;

49 }

50 //socket non-block mode set

51 if((ret = ioctlsocket(sockfd, FIONBIO, (unsigned long*)&ul))==SOCKET_ERROR)

52 {

53 closesocket(sockfd);

54 return -1;

55 }

56 sockaddr.sin_family = AF_INET;

57 sockaddr.sin_port = htons(port);

58 sockaddr.sin_addr.S_un.S_addr = inet_addr(argv[1]);

59

60 //connect to target ip with port

61 connect(sockfd, (SOCKADDR *)&sockaddr, sizeof(sockaddr));

62

63 https://www.doczj.com/doc/f310921501.html,_sec = timeout;

64 https://www.doczj.com/doc/f310921501.html,_usec = 0;

65 FD_ZERO(&fs);

66 FD_SET(sockfd,&fs);

67 ret = select(sockfd+1,NULL,&fs,NULL,&tv);

68 if(ret<0)

69 {

70 printf("Select Error\n");

71 closesocket(sockfd);

72 return -1;

73 }

74 else if(ret == 0)

75 {

76 printf(" %s %d Connect fail!\n",argv[1],port);

77 closesocket(sockfd);

78 return -1;

79 }

80 else

81 {

82 printf(" %s %d Connected success!\n",argv[1],port);

83 closesocket(sockfd);

84 }

85 WSACleanup(); //clean up Ws2_32.dll

86 return 0;

87 }

复制代码

2. Linux下TCP端口检测程序

复制代码

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv[])

{

int sockfd=socket(AF_INET,SOCK_STREAM,0);

struct sockaddr_in client;

char ip[20];

int port;

int timeout;

struct timeval tv;

if(argc != 4)

{

printf("Usage : %s ip port timeout\n", argv[0]);

exit(1);

}

strcpy(ip, argv[1]);

port = atoi(argv[2]);

timeout = atoi(argv[3]);

bzero(&client, sizeof(struct sockaddr_in));

client.sin_family = AF_INET;

client.sin_addr.s_addr = inet_addr(ip);

client.sin_port = htons(port);

https://www.doczj.com/doc/f310921501.html,_sec = 5;

https://www.doczj.com/doc/f310921501.html,_usec = 0;

//set timeout with setsockopt

if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv, sizeof(tv))<0)

{

perror("setsockopt failed\n");

exit(1);

}

if(setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&tv, sizeof(tv))<0)

{

perror("setsockopt failed\n");

exit(1);

}

if(!connect(sockfd,(struct sockaddr*)&client,sizeof(struct sockaddr_in)))

{

printf("connect ok\n");

}else{

printf("connect fail\n");

}

close(sockfd);

return 0;

}

相关主题
文本预览
相关文档 最新文档