windows下的socket(1)

winsock的初始化

进行winsock编程时,首先必须调用WSAStartup函数,设置程序中用到的Winsock版本,并初始化相应版本的库。

#include<winsock2.h>

int WSASartup(WORD   wVersionRequested   ,   LPWSADATA   lpWSAData  );
//成功时返回0,失败时返回非零的错误代码值。

  wVersionRequested     程序员要用的Winsock版本信息。
  lpWSAData                   WSADATA结构体变量的地址值

有必要给出上述两个参数的详细说明。第一个,Winsock中存在多个版本,应准备WORD类型的(WORD是通过typedef声明定义的unsiged short类型)套接字版本信息,并传递给该函数的一个参数wVersionRequested。若版本为1.2,则其中1是主版本号,2是副版本号,应传递0x0201。
  借助MAKEWORD宏函数则能轻松构建WORD型版本信息。

MAKEWORD(1  ,  2);   //主版本为1,副版本为2,返回0x0201
MAKEWORD(2  ,  2);   //主版本为2,副版本为2,返回0x0202

winsock库注销

#include<winsock2.h>
int WSACleanup();
//成功时返回0,失败时返回SOCKET_ERROR.

调用该函数时,winsock相关库将归还windows操作系统,无法再调用winsock相关函数。从原则上讲,无需再使用winsock函数时才调用该函数,但通常都在程序结束之前调用。


socket函数

//成功时返回socket句柄,失败时返回INVALID_SOCKET。

SOCKET socket(int af , int  type , int  protocol);
   af                  套接字中使用的协议族信息
   type              套接字数据传输类型信息
   protocol        计算机间通信中使用的协议信息

协议族类型:
                 PF_INET                                 IPv4互联网协议族
                 PF_INET6                               IPv6互联网协议族
                 PF_LOCAL                             本地通信的unix协议族
                 PF_PACKET                           底层套接字的协议族
                 PF_IPX                                   IPX  Novell协议族
    

套接字类型(type):       
1.面向连接的套接字(SOCK_STREAM)   
特点:
1)传输过程中数据不会消失
2)按顺序传输数据
3)传输的数据不存在数据边界

2.面向消息的套接字(SOCK_DGRAM)
特点:
1)强调快速传输而非传输顺序
2)传输的数据可能丢失也可能损毁
3)传输的数据有数据边界
4)限制每次传输的数据大小

3协议信息(填写0 根据前面的两个参数,默认填写合适的协议)
1)TCP套接字
socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
2)UDP套接字
socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);

bind函数

//成功时返回0,失败时返回SOCKET_ERROR
int bind(Socket s,const struct sockaddr * name,int namelen);
         s                  套接字句柄
      name              存有地址信息的结构体变量地址值
      namelen         第二个结构体变量的长度

listen函数

//成功时返回0,失败时返回SOCKET_ERROR
int listen(SOCKET s,int backlog);

accept函数

//成功时返回套接字句柄,失败时返回INVALID_SOCKET。
SOCKET accept(SOCKET s,struct sockaddr* addr,int * addrlen);

connect函数

//成功时返回0,失败时返回SOCKET_ERROR
int connect(SOCKET s,const struct sockaddr* name,int namelen);

cloessocket函数

//成功时返回0,失败时返回SOCKET_ERROR
int closesocket(SOCKET S);

传输函数

//成功时返回传输字节数,失败时返回SOCKET_ERROR
int send(SOCKET s, const char*buf , int len , int flags );
     s          表示数据传输对象连接的套接字句柄值
    buf        保存带传输数据的缓冲地址值
     len       要传输的字节数
    flags     传输数据时用到的多种选项信息

//成功时返回传输字节数(收到EOF时为0),失败时返回 SOCKET_ERROR
int recv(SOCKET s, const char*buf , int len , int flags );
     s          表示数据传输对象连接的套接字句柄值
    buf        保存带传输数据的缓冲地址值
     len       要传输的字节数
    flags     传输数据时用到的多种选项信息

服务器:

//服务器代码

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //显示调用ws2_32.lib

void ErrorHanding(char* message);
int main() {
	WSADATA wsadata;
	SOCKET hserverSocket, hclientSocket;
	SOCKADDR_IN serveraddr, clientaddr;
	int szClientAdd;
	char message[] = "这是服务器!";
	
	if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) //初始化winsock库
		ErrorHanding("WSAStartup() error");
	hserverSocket = socket(PF_INET, SOCK_STREAM, 0); // IPV4 面向连接传输
	if (hserverSocket == INVALID_SOCKET)
		ErrorHanding("socket() error");

	memset(&serveraddr, 0, sizeof(serveraddr));//清空,值全为0

	serveraddr.sin_family = AF_INET;    //IPv4
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);  //自动寻找本机地址
	serveraddr.sin_port = htons(6666);  //端口为 6666
	
	//绑定服务器地址
	if (bind(hserverSocket, (SOCKADDR*)&serveraddr, sizeof(serveraddr)) == SOCKET_ERROR)
		ErrorHanding("bind() error");
	//使套接字成为服务器套接字
	if (listen(hserverSocket,5) == SOCKET_ERROR) {
		ErrorHanding("listen() error");
	}
	szClientAdd = sizeof(clientaddr);
	hclientSocket = accept(hserverSocket, (SOCKADDR*)&clientaddr, &szClientAdd);
	if (hclientSocket == INVALID_SOCKET)
		ErrorHanding("accept() Error");

	send(hclientSocket, message, sizeof(message),0);

	closesocket(hclientSocket);  //关闭客户套接字
	closesocket(hserverSocket);  //关闭服务器套接字
	WSACleanup();  //清理winsock库
	return 0;
}
void ErrorHanding(char* message) {
	fputs(message, stderr);
	fputc('\n', stderr);
}
客户端代码:

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
void ErrorHanding(char* message);
int main() {
	WSADATA wsadata;
	SOCKET hclientsocket;
	SOCKADDR_IN servAddr;

	char message[30];
	int strlen;

	if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
		ErrorHanding("WSAStartup() error");
	hclientsocket = socket(PF_INET, SOCK_STREAM, 0);
	if (hclientsocket == INVALID_SOCKET)
		ErrorHanding("socket() error");

	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //回送地址,访问本地
	servAddr.sin_port = htons(6666); //端口号
	//客户端套接字通过目的地址建立连接
	if (connect(hclientsocket, (SOCKADDR*)&servAddr, sizeof(servAddr)))
		ErrorHanding("conect() error");
	//读取数据
	strlen = recv(hclientsocket, message, sizeof(message),0);
	if (strlen == -1) ErrorHanding(" read() error");

	printf("message from server:%s \n", message);
	getchar();
	closesocket(hclientsocket);
	WSACleanup();
	return 0;
}
void ErrorHanding(char* message) {
	fputs(message, stderr);
	fputc('\n', stderr);
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值