计算机网络课程设计——基于Windows socket编程的简易聊天机器人

来源:互联网 发布:淘宝上卖内衣的货源 编辑:程序博客网 时间:2024/06/07 01:30

1.了解基本的socket API函数
WSAStartup()和WSACleanup()函数的关系
WSAStartup()和WSACleanup()函数的关系
WSAStartup()函数
WSAStartup()函数
WSACleanup()函数
WSACleanup()
socket()函数
功能是创建套接字,客户端和服务端都要调用的函数,产生各自的套接字,两端之间传输数据都要用到套接字,可以认为是两个识别码,用来区别。
这里写图片描述
socket()函数第二个参数的选择方式,本例采用tcp,所以选SOCK_STREAM
这里写图片描述
Closesocket()函数
关闭套接字
这里写图片描述
bind()函数
功能是把套接字和IP地址绑定起来,在服务端调用
这里写图片描述
listen()函数
使服务端处于监听状态,在服务端调用
这里写图片描述
connect()函数
功能是连接服务端和客户端,在客户端调用
这里写图片描述
accpet()函数
建立第一次连接,之后开始正常通话,在服务端调用
这里写图片描述
send()函数,本例是TCP模式,采用send()函数,UDP模式采用sendto()函数
功能是发送数据
这里写图片描述
recv()函数,本例是TCP模式,采用recv()函数,UDP模式采用recvfrom()函数
功能是接收数据
这里写图片描述

//server.cpp#include "stdafx.h"#include <stdio.h>  #include <Winsock2.h> #include<stdlib.h>#pragma comment(lib, "WS2_32")//文件链表,文件里都是一个个字符串。一个字符串是问题,下一个字符串是回答,依次排列typedef struct node {    char data[100];    struct node *next;}*LinkList, *pNode;node *createlink(){    node *head = (node*)malloc(sizeof(node));    char t[100];    node *p;    node *q;    p  = head;    FILE * r = fopen("input.txt", "r");//问题和回答都当做字符串保存在名为input的txt文件    if (r == NULL)    {        printf("打开文件失败!");        return NULL;    }    while (fscanf(r, "%s", &t) != EOF)    {        q = (node*)malloc(sizeof(node));        strcpy(q->data, t);        p->next = q;        p = q;    }    p->next = NULL;    return head;}int main(){    node *head;    head = createlink();//建立链表    head = head->next;//因为第一个是空结点,直接指向头结点的下一个结点    WORD w;    WSADATA wsdata;    int err;    w = MAKEWORD(1, 1);//请求1.1的winsock版本    err = WSAStartup(w, &wsdata);//判断请求的winsock版本是否与本机相符合    if (err!=0)//如果不相符,err==0,直接退出    {        return -1;    }    if (LOBYTE(wsdata.wVersion)!=1||HIBYTE(wsdata.wVersion)!=1)    //再判断高低位是否都是1,确定是不是1.1的版本    {        WSACleanup();        return -1;    }    /*    SOCKADDR结构体和SOCKADDR_IN结构体的区别    struct SOCKADDR    {    unsigned short sa_family;    addressfamily,AF_xxx    char sa_data[14];    14bytesofprotocoladdress    }    struct SOCKADDR_IN    {    short sin_family;//Address family一般来说AF_INET(地址族)PF_INET(协议族)    unsigned short sin_port;//Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)    struct in_addr sin_addr;//IP address in network byte order(Internet address)    unsigned char sin_zero[8];//Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐    };    typedef struct in_addr    {    union{    struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;    struct { unsigned short s_w1,s_w2; } S_un_w;    unsigned long S_addr;    }S_un;    }IN_ADDR;    */    SOCKET socket1 = socket(AF_INET, SOCK_STREAM, 0);//创建套接字,三个参数都是TCP模式相关的    SOCKADDR_IN address;//定义结构体    address.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    /*sin_addr是一个联合体,用联合体就可以使用多种方式表示IP地址.一般我们使用其中的最后一种方式,即用无符号长整型数据来表示IP地址.此时,用的是s_nu数据成员,s_un是一个结构体,其中只有一个数据成员,即s_addr.    使用方式:        变量.sin_family = AF_INET;        变量.sin_addr.S_un.S.addr = htonl("IP地址");*/    address.sin_family = AF_INET;    address.sin_port = htons(1000);    //htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为:高位字节存放在内存的低地址处。    bind(socket1, (SOCKADDR*)&address, sizeof(SOCKADDR));    listen(socket1, 10);//处于监听状态    SOCKADDR_IN addrClient;//定义另一个结构体    int len = sizeof(SOCKADDR);    while (true)    {        SOCKET sockConn = accept(socket1, (sockaddr*)&addrClient, &len);        char sendBuf[100]="欢迎来到聊天机器人\n";        send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);//发送第一个字符串给客户端        char recvBuf[100];        recv(sockConn, recvBuf, 100, 0);        printf("%s", recvBuf);        while (true)//这里就是服务端和客户端的连接过程,一直进行        {            char recvBuf[100];            recv(sockConn, recvBuf, 100, 0);//接收客户端发送的字符串            printf("客户端说: %s\n",recvBuf);//打印客户端发送的字符串            char talk[100];            printf("你想说什么:");            while (strcmp(recvBuf, head->data)!=0)            //把客户端说的话当作字符串,在链表里找,并把它的下一句当作回答输出            {                head=head->next;//跳出时head->data就是客户端说的字符串后面的那个字符串            }            strcpy(talk, head->next->data);//拷贝给talk数组            send(sockConn, talk, strlen(talk) + 1, 0);//发送给客户端            printf("\n");        }        closesocket(sockConn);    }    return 0;}
//client.cpp#include "stdafx.h"#include<WinSock2.h>#pragma comment(lib,"WS2_32")int main(){    WORD w;    WSADATA wsadata;    int err;    w = MAKEWORD(1,1);    err = WSAStartup(w, &wsadata);    if (err!=0) {        return -1;        }    if (LOBYTE(wsadata.wVersion)!=1||HIBYTE(wsadata.wVersion)!=1)    {        WSACleanup();        return -1;    }    SOCKET sockclient = socket(AF_INET, SOCK_STREAM, 0);    SOCKADDR_IN ClientAddr;    ClientAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    ClientAddr.sin_family = AF_INET;    ClientAddr.sin_port = htons(1000);    connect(sockclient, (SOCKADDR*)&ClientAddr, sizeof(SOCKADDR));    char recvBuf[100];    recv(sockclient, recvBuf, 100, 0);    printf("%s\n", recvBuf);    send(sockclient, recvBuf, 100, 0);    printf("开始聊天!\n");    while (true)    {        char talk[100];        printf("请说:");        gets_s(talk);//获得输入的字符串并赋给talk数组        send(sockclient, talk, strlen(talk) + 1, 0);//把talk数组发送给服务端        char recvBuf[100];        recv(sockclient, recvBuf, 100, 0);//接收服务端发出的消息        printf("服务器说:%s\n", recvBuf);//打印服务端发送的消息    }    closesocket(sockclient);    WSACleanup();    return 0;}

我的文件只有三句话,所以没有考虑客户端输出的字符串不在文件内的情况,读者自行设计,加入判断语句
跟工程文件放在一起
这里写图片描述
建立两个win32控制台应用程序,分别命名server和client,代码输入完成之后先执行服务端,再执行客户端
运行效果图
这里写图片描述

阅读全文
0 0
原创粉丝点击