计算机网络课程设计——基于Windows socket编程的简易聊天机器人
来源:互联网 发布:淘宝上卖内衣的货源 编辑:程序博客网 时间:2024/06/07 01:30
1.了解基本的socket API函数
WSAStartup()和WSACleanup()函数的关系
WSAStartup()函数
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
- 计算机网络课程设计——基于Windows socket编程的简易聊天机器人
- 计算机网络课设之基于UDP协议的简易聊天机器人
- windows socket编程——多用户聊天
- 基于Java socket和多线程的简易聊天小程序
- 基于C# Winform的简易聊天程序[socket通信]
- 基于C# Winform的简易聊天程序[socket-文件发送]
- 基于C# Winform的简易聊天程序[socket-信息群发]
- Socket编程一实现简易的聊天功能以及文件传输
- Socket编程一实现简易的聊天功能以及文件传输
- 基于Windows的Socket编程
- 计算机网络——基于socket的网络应用
- 简易的聊天界面以及聊天机器人的实现
- 基于Udp的Socket网络编程聊天程序
- 基于Udp的Socket网络编程聊天程序
- 基于Socket和多线程编程的聊天程序实现
- 基于Java Socket编程的一对一聊天软件
- 两种开源聊天机器人的性能测试(二)——基于tensorflow的chatbot
- 两种开源聊天机器人的性能测试(二)——基于tensorflow的chatbot
- saltsack开启自动认证
- Markdown--从入门到精通(md源文件)
- Linux进程间通信——使用命名管道
- 求两个集合的交集
- 微信小程序日历
- 计算机网络课程设计——基于Windows socket编程的简易聊天机器人
- Kotlin中类和对象初始化
- 成员内部类、静态内部类、局部内部类、匿名内部类
- Python入门学习(4)
- javascript 对象判空
- java虚拟机指令详解
- 【剑指offer-解题系列(61)】把二叉树打印成多行
- 基于ZigBee的物联网环境数据采集系统
- EXCEL VBAProject密码破解 工作表密码破解