Winsock编程
1 客户端编程
a. WSAStartup (MAKEWORD(1,1), &WSAData)
初始化一个Winsock
MSDN解释The WSAStartup function initiates use of Ws2_32.dll by a process.
第一个参数是Winsock支持的最高版本,第二个参数是输出参数,用来获取Winsock的实现细节
包括支持的版本信息,socket的数目,系统信息等等。
b. ServerSock = socket (AF_INET, SOCK_STREAM, 0)
Create a TCP/IP socket that is bound to the server.创建一个用来连接server的socket
有必要看一下socket的定义
SOCKET socket(
int af,
int type,
int protocol
);
af
[in] Address family specification. 这个Address family specification是什么意思,在另一个资料
中查到 must be AF_INET. 与之对应的有一个native address family,这里就不深究了,应该就是IP地
址的表示类型
type
[in] Type specification for the new socket.
The following are the only two type specifications supported for Windows Sockets 1.1: Type
Explanation
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams with an OOB
data transmission mechanism. Uses TCP for the Internet address family.
SOCK_DGRAM Supports datagrams, which are connectionless, unreliable buffers of a fixed
(typically small) maximum length. Uses UDP for the Internet address family.
这个参数就是选择TCP还是UDP作为传输层协议
protocol
[in] Protocol to be used with the socket that is specific to the indicated address family.
c. phostent = gethostbyname (HOSTNAME)
retrieves host information corresponding to a host name from a host database
什么信息呢,主机的官方名称和host表里的域名
d. 初始化destination_sin,目标服务器的地址信息
包括使用的address family的类型, 端口, 主机名等
e. connect 建立与特定Socket的链接
int connect(
SOCKET s, 还未连接的socket的标识
const struct sockaddr FAR *name, 要连接的socket的地址,包括IP地址和端口号
int namelen
);
f. send 将字符串发送出去
int send(
SOCKET s, 链接好的socket
const char FAR *buf, 字符串指针
int len, 长度
int flags 发送的方式, MSDN中没有介绍
);
g. recv 得到返回的字符串
int recv(
SOCKET s,
char FAR *buf,
int len,
int flags
);
如果是面向连接的socket,这个socket要事先connect
如果是无连接的socket,要事先bound,不知道bound的具体含义是什么
当数据大小超过提供的buffer的大小时,对于链接的socket,sevice provider会保留着个
数据,直到提供更大的buffer,而对于无连接的socket,超出buffer大小的数据会被丢失
h. 结束处理
shutdown (ServerSock, 0x00);
// Close the socket.
closesocket (ServerSock);
WSACleanup ();
2 服务端
下面是服务端编程应该注意的几个函数
bound
给接受请求的socket指定主机名(IP)和端口,和客户端设置的IP和端口一致
listen
The listen function places a socket a state where it is listening for an incoming
connection.
int listen(
SOCKET s, 处于监听状态的socket的标识
int backlog 等待处理的连接的最大个数
);
accept
用于允许一个连接请求,并建立一个socket
如果没有请求则会一直等待,有点像getmessage
SOCKET accept(
SOCKET s, 接受请求服务端Socket
struct sockaddr FAR *addr, out参数,用于接收新建socket的Address
int FAR *addrlen, 缓冲区的大小
);
Winsock的是传输层之上,应用层之下的编程,与winInet相比,提供了更灵活的处理更底层数据结构的功
能,winInet好像只能处理http和ftp吧,但是winsock上可以自己定义数据格式。
我觉得winsock主要有两类socket,一类是server socket, 用来接收连接请求, 需要调用bound,
listen,accept函数;另一类是用于数据交换的socket, 主要调用connect, recv, send,这类socket
应该有一个输入缓冲区和一个输出缓冲区
下面是客户端和服务端代码,在VC6下通过编译并且显示正确,记住link里面要加上ws2_32.lib
客户端
#include <windows.h>
#include <winsock.h>
#define PORTNUM 5000 // Port number
#define HOSTNAME "localhost" // Server name string
// This should be changed
// according to the server.
int WINAPI WinMain (
HINSTANCE hInstance, // Handle to the current instance
HINSTANCE hPrevInstance,// Handle to the previous instance
LPTSTR lpCmdLine, // Pointer to the command line
int nCmdShow) // Show state of the window
{
int index = 0, // Integer index
iReturn; // Return value of recv function
char szClientA[100]; // ASCII string
TCHAR szClientW[100]; // Unicode string
TCHAR szError[100]; // Error message string
SOCKET ServerSock = INVALID_SOCKET; // Socket bound to the server
SOCKADDR_IN destination_sin; // Server socket address
PHOSTENT phostent = NULL; // Points to the HOSTENT structure
// of the server
WSADATA WSAData; // Contains details of the
// Winsocket implementation
// Initialize Winsocket.
if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
wsprintf (szError, TEXT("WSAStartup failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
// Create a TCP/IP socket that is bound to the server.
if ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Allocating socket failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
// Fill out the server socket's address information.
destination_sin.sin_family = AF_INET;
// Retrieve the host information corresponding to the host name.
if ((phostent = gethostbyname (HOSTNAME)) == NULL)
{
wsprintf (szError, TEXT("Unable to get the host name. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
// Assign the socket IP address.
memcpy ((char FAR *)&(destination_sin.sin_addr),
phostent->h_addr,
phostent->h_length);
// Convert to network ordering.
destination_sin.sin_port = htons (PORTNUM);
// Establish a connection to the server socket.
if (connect (ServerSock,
(PSOCKADDR) &destination_sin,
sizeof (destination_sin)) == SOCKET_ERROR)
{
wsprintf (szError,
TEXT("Connecting to the server failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
// Send a string to the server.
if (send (ServerSock, "gonglong the braveriest soldier", strlen ("gonglong the braveriest
soldier") + 1, 0)
== SOCKET_ERROR)
{
wsprintf (szError,
TEXT("Sending data to the server failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
}
// Disable sending on ServerSock.
shutdown (ServerSock, 0x01);
for (;;)
{
// Receive data from the server socket.
iReturn = recv (ServerSock, szClientA, sizeof (szClientA), 0);
// Check if there is any data received. If there is, display it.
if (iReturn == SOCKET_ERROR)
{
wsprintf (szError, TEXT("No data is received, recv failed.")
TEXT(" Error: %d"), WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Client"), MB_OK);
break;
}
else if (iReturn == 0)
{
MessageBox (NULL, szClientA, TEXT("Client"),
MB_OK);
break;
}
else
{
// Convert the ASCII string to a Unicode string.
for (index = 0; index <= strlen (szClientA); index++)
szClientW[index] = szClientA[index];
// Display the string received from the server.
MessageBox (NULL, szClientW, TEXT("Received From Server"), MB_OK);
}
}
// Disable receiving on ServerSock.
shutdown (ServerSock, 0x00);
// Close the socket.
closesocket (ServerSock);
WSACleanup ();
return TRUE;
}
服务端
#include <windows.h>
#include <winsock.h>
#define PORTNUM 5000 // Port number
#define HOSTNAME "localhost" // Server name string
int WINAPI WinMain (
HINSTANCE hInstance, // Handle to the current instance
HINSTANCE hPrevInstance,// Handle to the previous instance
LPTSTR lpCmdLine, // Pointer to the command line
int nCmdShow) // Show state of the window
{
SOCKET ServerSock, // IR socket bound to the server
ClientSock; // IR socket bound to the client
//SOCKADDR_IRDA address = {AF_IRDA, 0, 0, 0, 0, "IRServer"};
SOCKADDR_IN server_sin; // Server socket address
// Specifies the server socket address
int index = 0, // Integer index
iReturn; // Return value of recv function
char szServerA[100]; // ASCII string
TCHAR szServerW[100]; // Unicode string
TCHAR szError[100]; // Error message string
WSADATA WSAData; // Contains details of the
PHOSTENT phostent = NULL; // Points to the HOSTENT structure
// Winsocket implementation
// Initialize Winsocket.
if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
wsprintf (szError, TEXT("WSAStartup failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
// Create a socket bound to the server.
if ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Allocating socket failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
if ((phostent = gethostbyname (HOSTNAME)) == NULL)
{
wsprintf (szError, TEXT("Unable to get the host name. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
server_sin.sin_family = AF_INET;
// Assign the socket IP address.
memcpy ((char FAR *)&(server_sin.sin_addr),
phostent->h_addr,
phostent->h_length);
// Convert to network ordering.
server_sin.sin_port = htons (PORTNUM);
// Associate the server socket address with the server socket.
if (bind (ServerSock, (struct sockaddr *)&server_sin, sizeof (server_sin))
== SOCKET_ERROR)
{
wsprintf (szError, TEXT("Binding socket failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
// Establish a socket to listen for incoming connections.
if (listen (ServerSock, 5) == SOCKET_ERROR)
{
wsprintf (szError,
TEXT("Listening to the client failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
// Accept a connection on the socket.
if ((ClientSock = accept (ServerSock, 0, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Accepting connection with client failed.")
TEXT(" Error: %d"), WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
}
// Stop listening for connections from clients.
closesocket (ServerSock);
// Receive data from the client.
iReturn = recv (ClientSock, szServerA, sizeof (szServerA), 0);
// Check if there is any data received. If there is, display it.
if (iReturn == SOCKET_ERROR)
{
wsprintf (szError, TEXT("No data is received, recv failed.")
TEXT(" Error: %d"), WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Server"), MB_OK);
}
else if (iReturn == 0)
{
MessageBox (NULL, szServerA, TEXT("Received Data"),
MB_OK);
}
else
{
// Convert the ASCII string to a Unicode string.
for (index = 0; index <= strlen (szServerA); index++)
szServerW[index] = szServerA[index];
// Display the string received from the client.
MessageBox (NULL, szServerW, TEXT("Received From Client"), MB_OK);
}
TCHAR szReply[200] = "hello, ";
strcat(szReply, szServerA);
// Send a string from the server socket to the client socket.
if (send (ClientSock, szReply, strlen (szReply) + 1, 0)
== SOCKET_ERROR)
{
wsprintf (szError,
TEXT("Sending data to the client failed. Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
}
// Close the client and server sockets.
closesocket (ClientSock);
return 0;
}
本文介绍了Winsock编程的基础知识,包括客户端和服务端编程流程。详细解释了WSAStartup、socket、connect、bind、listen、accept等关键函数的作用及使用方法。
5489

被折叠的 条评论
为什么被折叠?



