windows套接字编程
1、设置库Alt+F7 ->“配置属性”-> “连接器” -> “输入” -> “附加依赖项” -> “ws2_32.lib”
2、头文件:#include <winsock2.h>
3、Winsock的初始化
- 首先必须调用WSAStartup函数,设置程序中用到的Winsock版本,并初始化响应版本的库。
- int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSData);
- 成功时返回0, 失败时返回非零的错误代码值。
- wVersionRequested 是Winsock的版本信息。
- lpWSData WSADATA结构体变量的地址值
- 借助MAKEWORD宏函数构建WORD型版本信息,
- 如:MAKEWORD(1, 2);表示主版本为1,副版本为2,返回0x0201
4、Winsock的注销
- int WSAClenup();
- 成功时返回0, 失败时返回SOCKET_ERROR。
- 调用该函数时,Winsock相关库归还Windows操作系统,无法再调用Winsock相关函数
- server.cpp
// server.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <WinSock2.h>
void EfforHandling(char *message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClientSock;
SOCKADDR_IN servAddr, clntAddr;
int szClntAddr;
char message[] = "Hello World!";
if (argc != 2)
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
EfforHandling("WSAStartup() error!");
}
hServSock = socket(PF_INET, SOCK_STREAM, 0);
if (hServSock == INVALID_SOCKET)
{
EfforHandling("socket() error!");
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(atoi(argv[1]));
if (bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
EfforHandling("bind() error!");
}
if (listen(hServSock, 5) == SOCKET_ERROR)
{
EfforHandling("listen() error!");
}
szClntAddr = sizeof(clntAddr);
hClientSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
if (hClientSock == INVALID_SOCKET)
{
EfforHandling("accept() error!");
}
send(hClientSock, message, sizeof(message), 0);
closesocket(hClientSock);
closesocket(hServSock);
WSACleanup();
system("pause");
return 0;
}
void EfforHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
- client.cpp
// client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <WinSock2.h>
void EfforHandling(char *message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAddr;
char message[30];
int strLen;
if (argc != 3)
{
printf("Usage : %s <IP> <PORT>\n", argv[0]);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
EfforHandling("WSAStartup() error!");
}
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET)
{
EfforHandling("socket() error!");
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(argv[1]);
servAddr.sin_port = htons(atoi(argv[2]));
if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
printf("connect() error %ld\n", WSAGetLastError());
EfforHandling("connect() error!");
}
strLen = recv(hSocket, message, sizeof(message)-1, 0);
if (strLen == -1)
{
EfforHandling("recv() error!");
}
printf("Message from server: %s \n", message);
closesocket(hSocket);
WSACleanup();
system("pause");
return 0;
}
void EfforHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
- server运行参数设置 visual studio ->PROJECT->Configuration Properties->Debuggins->Command Arguments->9018
- client运行参数设置 visual studio ->PROJECT->Configuration Properties->Debuggins->Command Arguments->127.0.0.1 9018
先运行server,再运行client
windows和linux对套接字的I/O操作不同
window对winsock的写操作
int send(SOCKET s, const char *buf, int len, int flags);
1、s 表示数据传输对象连接的套接字句柄值
2、buf 保存待传输数据的缓冲地址值
3、len 要传输的字节数
4、flags 传输数据时用到的多种选项信息
5、成功是返回传输字节数,失败时返回SOCKET_ERRORwindow对winsock的读操作
int recv(SOCKET s, const char *buf, int len, int flags);
1、s 表示数据接收对象连接的套接字句柄值
2、buf 保存接收数据的缓冲地址值
3、len 能够接收的最大字节数
4、flags 接收数据时用到的多种选项信息
5、成功是返回接收字节数(收到EOF时为0),失败时返回SOCKET_ERROR请不要误认为linux中的read、write函数就是对应于Windows的send、recv函数。