How to make fundamental Winsock calls to set up communication using the internet Protocol
what is the LANs ?local area networks while what is the WANs? wide area networks
In Winsock,applications specify IP addresses and service port information through the SOCKADDR_IN structure,which is defined as:
struct sockaddr_in
{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
sin_family must be set to AF_INET,
unsigned long inet_addr(const char FAR *cp);//converts a dotted IP address to a 32-bit unsigned long integer quantity ,
4 bytes of an internet address
4*8=32
1byte=8bits
four –part address and three –part address the last part is interpreted as a 16-bit quantity and placed in the right-most 2bytes of the network address.”128.net.host'' CLASS B
two-part address CLASS A
inet_ntoa() Function
converts an (Ipv4) Internet network address into a string in Internet standard dotted-decimal format
The syntax is : char *FAR inet_ntoa(_in struct in_addr in);
the in is an in_addr structure that represents an internet host address
if no error occurs,inet_ntoa() returns a character pointer to a static buffer containing the text address in standard
otherwise it returns NULL
Notice:this application should not any assumption about the way in which the memory is allocated
the string returned is guaranteed to be valid only until the next Windows Socks function call is made within the thread.
Therefore,the data should be copied before another Windows Sockets call is made.
InetNtop() function
PCTSTR WSAAPI InetNtop (
_in INT Family ,
_in PVOID pAddr,
_out PTSTR pStringBuf,
_in size_t StrinBufSize
);
the Family is an address family ,The possible values for the address family are defined in the Ws2def.h head file.Note that the Ws2def.h header file is automatically included in Winsock2.h
pAddr is a pointer to the IP address in network byte to convert to a string.
when the Family parameter is AF_INET
UNICODE:双字节对字符进行编码的编码标准.
The IN_ADDR structure is defined in the Inaddr.h header file. The IN6_ADDR structure is defined in the In6addr.h header file.
The IN_ADDR structure is defined in the Inaddr.h header file. The IN6_ADDR structure is defined in the In6addr.h header file.
InetPton()Function
PCTSTR WSAAPI inet_pton()
_in INT Family,
_in PCTSTR pszAddrString,
_out PVOID pAddrBuf
);
The Family is the address family. Possible values for the address family are defined in the Ws2def.h header file
The pszAddrString is a pointer to the NULL-terminated string that contains the text representation of the IP address to convert to numeric binary form
When the Family parameter is AF_INET, then the pszAddrString parameter must point to a text representation of an IPv4 address in standard notation
The pAddrBuf is a pointer to a buffer in which to store the numeric binary representation of the IP address. The IP address is returned in network byte order. When the Family parameter is AF_INET, this buffer should be large enough to hold an IN_ADDR structure
If no error occurs, the InetPton() function returns a value of 1 and the buffer pointed to by the pAddrBuf parameter contains the binary numeric IP address in network byte order.
The InetPton() function is supported on Windows Vista and later.
While the inet_addr function works only with IPv4 address strings, the InetPton function works with either IPv4 or IPv6 address strings.
Other functions that are supported on Windows Vista and later include RtlIpv4AddressToString(), RtlIpv4StringToAddress(), RtlIpv4StringToAddressEx(), RtlIpv6AddressToString(), RtlIpv6AddressToStringEx(), RtlIpv6StringToAddress(), RtlIpv6StringToAddressEx().
Byte Ordering
The following four API functions convert a number from host-byte to network-byte order:
The next four functions are the opposite of the preceding four functions; they convert network-byte order to host-byte order.
Creating a Socket
SOCKET in WINSOCK2.H. There are two functions that can be used to create a socket: socket and WSASocket. In the simplest form, we will briefly describe socket as:SOCKET socket (
int af,
int type,
int protocol
);
Winsock features four useful functions to control various socket options and socket behaviors: setsockopt(), getsockopt(), ioctlsocket(), and WSAIoctl().
In Winsock there are two basic communication techniques: connection-oriented and connectionless communication.
In IP, connection-oriented communication is accomplished through the TCP/IP protocol
Server API Functions
The first step in Winsock is to create a socket with either the socket() or WSASocket() call and bind the socket of the given protocol to its well-known name, which is accomplished with the bind() API call.
Binding, bind()
The bind() function associates the given socket with a well-known address
int bind(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
Listening, listen()
The next piece of the equation is to put the socket into listening mode
int listen(SOCKET s, int backlog);
Accepting Connections, accept()
Now you're ready to accept client connections. This is accomplished with the accept(), WSAAccept(), or AcceptEx() function. (AcceptEx(), an extended version of accept similar to other Win32 Ex versions) The prototype for accept is:
SOCKET accept(
SOCKET s,
struct sockaddr FAR* addr,
int FAR* addrlen
);
At this point, we have described all the necessary elements to construct a simple Winsock TCP/IP server application. The following program example demonstrates how to write a simple server that can accept one TCP/IP connection. We did not perform full error checking on the calls to make reading the code less confusing.
实验情况:
tcpserve.cpp
Linking...
tcpserve.obj : error LNK2001: unresolved external symbol __imp__accept@12
tcpserve.obj : error LNK2001: unresolved external symbol __imp__listen@8
tcpserve.obj : error LNK2001: unresolved external symbol __imp__closesocket@4
tcpserve.obj : error LNK2001: unresolved external symbol __imp__bind@12
tcpserve.obj : error LNK2001: unresolved external symbol __imp__htonl@4
tcpserve.obj : error LNK2001: unresolved external symbol __imp__htons@4
tcpserve.obj : error LNK2001: unresolved external symbol __imp__socket@12
tcpserve.obj : error LNK2001: unresolved external symbol __imp__WSACleanup@0
tcpserve.obj : error LNK2001: unresolved external symbol __imp__WSAGetLastError@0
tcpserve.obj : error LNK2001: unresolved external symbol __imp__WSAStartup@8
Debug/Tcpservicerc.exe : fatal error LNK1120: 10 unresolved externals
Error executing link.exe.
根据高人指点,添加#pragma comment(lib, "ws2_32.lib"),就okl,想起来,好像在winsock编程1中,没有出现过,可能在setup中出现问题.
注意到:
9. Manually, type the library name, ws2_32.lib and click OK. Or you can just directly type the library name in the empty field on the right of the Additional Dependencies. Click OK.
//
#pragma comment 的用法实在是太多了,可以告诉你的是 #pragma comment(lib,"Ws2_32.lib")表示链接Ws2_32.lib这个库。 和在工程设置里写上链入Ws2_32.lib的效果一样,不过这种方法写的 程序别人在使用你的代码的时候就不用再设置工程settings了。
#pragma comment( comment-type ,[commentstring] )
CODE:
#include<winsock2.h>
#include<stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main (void)
{
WSADATA wsaData;
SOCKET ListeningSocket;
SOCKET NewConnection;
SOCKADDR_IN ServerAddr;
int Port=5150;
if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf("Server:WSAStarup failed with error%ld\n",WSAGetLastError());
return -1;
}
else
{
printf("Server:The Winsock dll found!\n");
printf("Server:The current status is %s.\n",wsaData.szSystemStatus);
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
printf("Server:The dll do not support the Winsock version %u.%u!\n",LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
WSACleanup();
return -1;
}
else
{
printf("Server:The dll do not supports the Winsock version %u.%u!\n",LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
printf("Server:The highest version this dll can support is %u.%u\n",LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
}
//Create a new socket to listen for client connections
ListeningSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (ListeningSocket==INVALID_SOCKET)
{ printf("Server:Error ar socket(),erroor code:%ld\n",WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("Server:socket()is OK!\n");
//set up a SOCKADDR_IN structure that will tell bind that we want to listen for connections on all interfaces using the port 5150;
//The IPv4 family
ServerAddr.sin_family=AF_INET;
//host-to-network byte order
ServerAddr.sin_port=htons(Port);
//Listen on all interface,host-to-network byte order
ServerAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if(bind(ListeningSocket,(SOCKADDR*)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR)
{
printf("Server:bind()failed!Error code :%ld.\n",WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
return -1;
}
else
printf("Server :bind() is OK!\n");
//Listen for client connections,We used a backlog of 5 ,which is normal for many application.
if(listen(ListeningSocket,5)==SOCKET_ERROR)
{
printf("Server:listen():Error listening on socket %ld\n",WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
return -1;
}
else
printf("Server:listen() is OK,I'm waiting for connections ..\n");
printf("Server:accept()is ready ..\n");
while(1)
{
NewConnection=SOCKET_ERROR;
while(NewConnection==SOCKET_ERROR)
{
NewConnection=accept(ListeningSocket,NULL,NULL);
}
printf("Server:accept() is OK..\n");
printf("Server:Client connected ,ready for receiving and sending data..\n");
//Transfer the connected socket to the listening socket
ListeningSocket=NewConnection;
break;
}
if (closesocket(NewConnection)!=0)
printf("Server:Cannot close\"NewConection\"socket.Error code:%ld\n",WSAGetLastError());
else
printf("Server:Closing\"NewConnection\"socket..\n");
if(WSACleanup()!=0)
printf("Server:WSAClenup()failed! Error code:%ld\n",WSAGetLastError());
else
printf("Server:WSACleanup()isOK..\n");
return 0;
}