Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Some functional Analysis of socket

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces some functional analysis of socket, the content is very detailed, interested friends can refer to, hope to be helpful to you.

In network programming, the most commonly used and basic is WINSOCK. Now let's talk about SOCKET programming under WINDOWS.

Most WINSOCK programming on the WIN32 platform goes through the following steps:

Define variable-> get WINDOCK version-> load WINSOCK library-> initialize-> create socket-> set socket options-> close socket-> uninstall WINSOCK library-> release resources

The following describes the process of establishing WINSOCK Cramp S:

Server client

_ _ _

1 initialize WSA 1 initialize WSA

_ _ _

2 build a SOCKET 2 set up a SOCKET

_ _ _

3 bind SOCKET 3 to connect to the server

_ _ _

4 listen on the specified port 4 send and receive data

_ _ _

5 accept a connection 5 disconnect

_ _-

6 send and receive data

_ _ _

7 disconnect

_ _ _

Note that when you program WINSOCK in VC, you need to introduce the following two library files: WINSOCK.H (this is the header file of WINSOCK API, and WINSOCK2 is supported above WIN2K, so

You can use WINSOCK2.H); Ws2_32.lib (WINSOCK API link library file).

The mode of use is as follows:

# include

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

Let's demonstrate the workflow of the server and client through specific code:

First, set up a WSADATA structure, usually using wsaData

WSADATA wsaData

Then, call the WSAStartup function, which is the first call to connect the application to winsock.dll. Where the first parameter is the WINSOCK version number, and the second parameter is to point to

The pointer of WSADATA. This function returns an int value, which is checked to determine whether initialization is successful. The format of the call is as follows: WSAStartup (MAKEWORD (2d2), & wsaData), where

MAKEWORD (2) means to use the WINSOCK2 version .wsaData to store the information about WINSOCK sent back by the system.

If (iResuit=WSAStartup (MAKEWORD (2Magazine 2), & wsaData)! = 0)

{

Printf ("WSAStartup failed:%d", GetLastError ()); / / the returned value is not equal to 0, indicating initialization failed

ExitProcess (); / / exit the program

}

After the application finishes using the requested SOCKET library, it calls the WSACleanup function to contact the binding of the SOCKET library and release the resources.

Note that after WSAStartup initialization, a SOCKET structure must be established to hold the SOCKET handle.

Let's build a SOCKET.

First we set up a SOCKET handle of m_socket, then call the socket () function, and the return value of the function is stored in m_socket. We use AF_INFE,SOCK_STREAM,IPPROTO_TCP

Three parameters. The first represents the address family, AF_INFE represents the TCP/ IP family, and the second represents the service type. In WINSOCK2, SOCKET supports the following three types

SOCK_STREAM streaming socket

SOCK_DGRAM Datagram socket

SOCK_RAW raw socket

The third parameter represents the protocol:

IPPROTO_UDP UDP protocol for connectionless Datagram sockets

IPPROTO_TCP TCP protocol for streaming sockets

IPPROTO_ICMP ICMP protocol is used for raw sockets

M_socket=socket (AF_INFE,SOCK_STREAM,IPPROTO_TCP); / / create TCP protocol

The following code is used to check the return value for errors:

If (m_scoket==INVALID_SOCKET)

{

Prinrf ("Error at socket ():% DBO", GetLastError ())

WSACleanup (); / / release resources

Return

}

Note that if the socket () call fails, he will return INVALID_SOCKET.

In order for the server to accept a connection, it must bind a network address. The following code shows how to bind an initialized IP and port Socket. The client program uses this.

IP address and port to connect to the server.

Sockaddr_in service

Service.sin_family=AF_INET; / / INTERNET address family

Service.sin_addr.s_addr=inet_addr ("127.0.0.1"); / / the local IP address to be bound

Service.sin_port=htons (27015); / / 27015 the port to be bound

Next we call the BIND function, pass in SOCKET and SOCKADDR as arguments, and check for errors.

If (bind (m_socket, (SOCKADDR*) & SERVICE,sizeof (service)) = = SOCKET_ERROR)

{

Printf ("bind () failed./n")

Closesocket (m_socket)

Return

}

When the binding is complete, the server must establish a listening queue to accept requests from the client. Listen () makes the server listen. The function call returns 0 successfully, otherwise it returns

SOCKET_ERROR. The code is as follows:

If (listen (masked socketMagne1) = = SOCKET-ERROR)

{

Printf ("error listening on socket./n")

}

After the server calls LISTEN (), if the client calls the CONNECT () function at this time, the server must call ACCEPT (). In this way, the server and the client can officially complete the communication program.

Connect the action.

Once the server starts listening, we specify a handle to represent the connection accepted by the ACCEPT () function, which is used to send and receive data. Create a SOCKET handle

Socket AcceptSocket then uses an infinite loop to detect whether a connection is coming in. As soon as there is a connection request, the ACCEPT () function is called and returns the handle to the connection.

Printf ("waitong for a client to connect.../n")

While (1)

{

AcceptSocket=SOCKET_ERROR

While (AcceptSocket==SOCKET_ERROR)

{

AcceptSocket=accept (masked socket _ null _ null)

}

}

Let's look at the client-side code:

Sockaddr_in clientService

ClientService.sin_family=AF_INET; / / INTERNET address family

ClientService.sin_addr.s_addr=inet_addr ("127.0.0.1"); / / the local IP address to be bound

ClientService.sin_port=htons (27015); / / 27015 the port to be bound

The CONNECT () function is called as follows:

If (connect (m_socket, (SOCKADDR*) & clientService, sizeof (clientService)) = = SOCKET_ERROR)

{

Printf ("Failed to connect./n")

WSACleanup ()

Return

} / / Clean out if the call fails

/ / the call continues to read and write data successfully

_

At this point, the basic flow of the server and client is introduced, and let's introduce the data exchange.

Send ():

Int send

{

SOCKET s, / / specify the sending end socket

Const char FAR?*buf, / / indicates a buffer for data to be sent by the application

Int len, / / actual number of bytes of data to be sent

Int flags / / is generally set to 0

}

The SEND function is used to send data to the other end of the TCP connection.

Recv ():

Int recv

{

SOCKET s, / / specify the sending end socket

Char FAR?*buf, / / indicates a buffer to store the data received by RECC

Int len, / / indicates the length of the BUF

Int flags / / is generally set to 0

}

The RECV function is used to accept data from the other end of the TCP connection.

The following complete program code is provided as follows. You can compile and run the client code directly: # include # include # pragma comment (lib, "ws2_32.lib") void main () {/ / initialize Winsock. WSADATA wsaData; int iResult = WSAStartup (MAKEWORD (2jing2), & wsaData); if (iResult! = NO_ERROR) printf ("Error at WSAStartup () / n"); / / establish socket socket. SOCKET client; client = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client = = INVALID_SOCKET) {printf ("Error at socket ():% ld/n", WSAGetLastError ()); WSACleanup (); return;} / / Connect to the server. Sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr ("127.0.0.1"); clientService.sin_port = htons (27015); if (connect (client, (SOCKADDR*) & clientService, sizeof (clientService)) = = SOCKET_ERROR) {printf ("Failed to connect./n"); WSACleanup (); return;} / / send and receive data. Int bytesSent; int bytesRecv = SOCKET_ERROR; char sendbuf [32] = "Client: Sending data."; char recvbuf [32] = ""; bytesSent = send (client, sendbuf, strlen (sendbuf), 0); printf ("Bytes Sent:% ld/n", bytesSent); while (bytesRecv = = SOCKET_ERROR) {bytesRecv = recv (client, recvbuf, 32,0); if (bytesRecv = 0 | bytesRecv = = WSAECONNRESET) {printf ("Connection Closed./n"); break;} if (bytesRecv)

< 0) return; printf( "Bytes Recv: %ld/n", bytesRecv ); } return; } 下面是服务器端代码: #include #include #pragma comment(lib, "ws2_32.lib") void main() { // 初始化 WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) printf("Error at WSAStartup()/n"); // 建立socket SOCKET server; server = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( server == INVALID_SOCKET ) { printf( "Error at socket(): %ld/n", WSAGetLastError() ); WSACleanup(); return; } // 绑定socket sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr( "127.0.0.1" ); service.sin_port = htons( 27015 ); if ( bind( server, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) { printf( "bind() failed./n" ); closesocket(server); return; } // 监听 socket if ( listen( server, 1 ) == SOCKET_ERROR ) printf( "Error listening on socket./n"); // 接受连接 SOCKET AcceptSocket; printf( "Waiting for a client to connect.../n" ); while (1) { AcceptSocket = SOCKET_ERROR; while ( AcceptSocket == SOCKET_ERROR ) { AcceptSocket = accept( server, NULL, NULL ); } printf( "Client Connected./n"); server = AcceptSocket; break; } // 发送接受数据 int bytesSent; int bytesRecv = SOCKET_ERROR; char sendbuf[32] = "Server: Sending Data."; char recvbuf[32] = ""; bytesRecv = recv( server, recvbuf, 32, 0 ); printf( "Bytes Recv: %ld/n", bytesRecv ); bytesSent = send( server, sendbuf, strlen(sendbuf), 0 ); printf( "Bytes Sent: %ld/n", bytesSent ); return; } 本程序仅仅描述了同步的情况! PS:本文转自百度贴吧新红盟吧 转自:http://blog.csdn.net/LaoWu_/archive/2010/04/08/5461077.aspx关于gethostname函数失败的问题 调用gethostname之前, 要先调用WSAStartup才可以, 否则gethostname会失败! 下面是正确的代码 view plaincopy to clipboardprint? #include #include #include #include #include #pragma comment(lib, "Ws2_32") int main() { WSADATA wsData; ::WSAStartup(MAKEWORD(2,2), &wsData); char szIP[32] = {0}; char szHostName[32] = {0}; int iResult = ::gethostname(szHostName, sizeof(szHostName)); if (iResult != 0) { printf("error/n"); return -1; } printf("%s/n", szHostName); hostent *pHost = ::gethostbyname(szHostName); ::WSACleanup(); return 0; } 转自:http://blog.csdn.net/leesphone/archive/2008/03/02/2138775.aspx gethostbyname用法使用这个东西,首先要包含2个头文件: #include #include struct hostent *gethostbyname(const char *name); 这个函数的传入值是域名或者主机名,例如"www.google.com","wpc"等等。 传出值,是一个hostent的结构(如下)。如果函数调用失败,将返回NULL。 struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; 解释一下这个结构, 其中: char *h_name 表示的是主机的规范名。例如www.google.com的规范名其实是www.l.google.com。 char **h_aliases 表示的是主机的别名。www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。 int h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是ipv6(AF_INET6) int h_length 表示的是主机ip地址的长度 int **h_addr_lisst 表示的是主机的ip地址,注意,这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西,会有问题的哇。所以到真正需要打印出这个IP的话,需要调用inet_ntop()。 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) : 这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。 这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。 下面是例程,有详细的注释。 #include #include int main(int argc, char **argv) { char *ptr,**pptr; struct hostent *hptr; char str[32]; /* 取得命令后第一个参数,即要解析的域名或主机名 */ ptr = argv[1]; /* 调用gethostbyname()。调用结果都存在hptr中 */ if( (hptr = gethostbyname(ptr) ) == NULL ) { printf("gethostbyname error for host:%s/n", ptr); return 0; /* 如果调用gethostbyname发生错误,返回1 */ } /* 将主机的规范名打出来 */ printf("official hostname:%s/n",hptr->

H_name)

/ * the host may have multiple aliases. Type all aliases separately * /

For (pptr = hptr- > hackers; * pptr! = NULL; pptr++)

Printf ("alias:%s/n", * pptr)

/ * type the address according to the address type * /

Switch (hptr- > h_addrtype)

{

Case AF_INET:

Case AF_INET6:

Pptr=hptr- > h_addr_list

/ * type out all the addresses you just got. The inet_ntop () function * / is called.

For (; * pptryside null +)

Printf ("address:%s/n", inet_ntop (hptr- > h_addrtype, * pptr, str, sizeof (str))

Break

Default:

Printf ("unknown address type/n")

Break

}

Return 0

}

Transferred from: http://blog.csdn.net/chollima/archive/2010/06/04/5648065.aspx

Gethostname and gethostbyname,inet_ntoaview plaincopy to clipboardprint?

/ / socketTest.cpp: Defines the entry point for the console application.

/ /

# include "stdafx.h"

# include

# include

Using namespace std

Int _ tmain (int argc, _ TCHAR* argv [])

{

WSADATA wsData = {0}

Int nRet =:: WSAStartup (MAKEWORD (2,2), & wsData)

Char szBuf [Max _ PATH] = {0}

:: gethostname (szBuf, MAX_PATH); / / get the computer name

Struct hostent* pStHostent = NULL

Strcpy (szBuf, "www.google.com")

PStHostent =:: gethostbyname (szBuf); / / pass in the domain name or hostname to get the host structure

/ *

PStHostent- > hsignname; / / Specification name

PStHostent- > html addrtypespare / address type IPV4 or IPV6

The IP address of pStHostent- > hobbies, listeners, racket, etc

PStHostent- > html address length; / / ip address length

PStHostent- > html aliasesumbent / host alias

, /

Cout h_name h_addrtype)

{

Case AF_INET:

Case AF_INET6:

Pptr = pStHostent- > h_addr_list

For (; * pptr! = NULL; pptr++)

{

/ / addr.S_un.S_addr = * (upright long *) * pptr

Addr.s_addr = * (upright long *) * pptr

/ / print out a list of IP addresses

Cout

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report