Socket网络编程(一)

此文使用的协议是 TCP

 

    首先要写入以下代码,不然很多函数都用不了

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

 

服务器端

    第一步我们要导入套接字库。

WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsadata;
int result = WSAStartup(wVersionRequested, &wsadata);

WORD有人可能不知道它是啥

看一看源代码就可以看到它是这样定义的

typedef unsigned short WORD   //无符号短整数

 

还有WSAStartup函数,它的原型是这样的

int WSAStartup(WORD wVersionRequested,LPWSADATA IpWSAData);

第一个参数表示windows socket版本,高字节是修订版本号,低字节是主版本号;

第二个参数记录windows socket版本的相关信息,并且是指针变量;

这个函数有返回值,返回0时表示成功,其他值表示失败。

 

有时我们写服务器时为了防止套接字库加载错误可以写以下代码

if (result != 0)
    {
        printf("套接字加载失败!");
        return 0;
    }

if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
    {
        printf("套接字版本错误!");
        return 0;
    }

当然socket有不同的版本,这里只是做个示范

 

    第二步创建套接字SOCKET

源代码是这样定义的

typedef unsigned int UINT_PIR
typedef UINT_PIR  SOCKET

所以SOCKET也是一个无符号整型数据

 

创建套接字要用到socket函数,函数原型是这样的

SOCKET _stdcall socket(int af,int type,int protocol)

af是address family的缩写,就是地址簇

type就是使用的协议类型,一共有三种

1、流式套接字(SOCK_STREAM):用到的协议TCP 

2、数据包套接字(SOCK_DGRAM):无连接的,不可靠的UDP

3、原始套接字(SOCK_RAW)

而protocol就是与特定的地址簇相关的协议,一般填0就行了,现在举个例子

SOCKET sockSrv = socket( AF_INET      //Internet 协议  地址簇
                        SOCK_STREAM, //套接字协议
                        0            //与特定的地址簇相关的协议
);

 

  第三步绑定套接字

//bind绑定套接字,参数一服务器套接字,参数二服务器套接字地址,参数三套接字地址大小
SOCKADDR_IN sockaddr;
sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(1234);
if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)))
    {
        printf("绑定套接字失败!");
        return 0;
    };

那个 INADDR_ANY 表示的是任意地址的意思,因为服务器的地址是不确定的,所以填这个,当然你想改也可以改,只要改的对,还有端口随便找个不常用到的就行。

 

    第四步将套接字设置为监听模式

//   参数一服务器套接字,参数二等待连接队列最大长度
if (SOCKET_ERROR == listen(sockSrv, 5))
    {
        printf("监听失败!");
        return 0;
    }

 

    第五步接受客户端

// 参数一服务器套接字,参数二客户端套接字,参数三客户端套接字的长度
SOCKADDR_IN clientaddr;
int nLength = sizeof(SOCKADDR);
SOCKET sockcon = accept(sockSrv, (SOCKADDR*)&clientaddr, &nLength);

 

    第六步发送/接受信息

函数原型int_stdcall send(SOCKET s,const char *buf,int len,int flags)

随便举个例子

char temp[100];
sprintf(temp, "欢迎 %s 进入聊天室!\n", inet_ntoa(clientaddr.sin_addr));//字符串是客户端的地址
send(sockCon, temp, strlen(temp) + 1, 0);
char temp[256];
recv(sockCon, tmep, 100, 0) 
printf("%s", temp);

 

    最后要记得关闭套接字,不然有时会出现意外情况

closesocket(sock);
WSACleanup();

 

●客户端

    第一步与服务器端一样加载套接字库,就不说了

    第二步创建套接字

SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);

    第三步连接服务器

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//测试所以就用本地的了
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(1234); //端口随便写一个1024之后的,也就是不常用的,不过要与服务器的一样
//参数一客户端套接字,参数二服务器地址信息,参数三套接字地址大小
if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
    {
        printf("服务器连接失败!");
        return 0;
    }

    第四步发送/接受信息,与之前的一样,也不说了

   当然最后也别忘了关闭套接字

 

posted @ 2018-10-17 17:53  贺墨于  阅读(638)  评论(0编辑  收藏  举报