基于SOCKET的聊天程序

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

三、系统详细设计 程序流程图:
服务器 开始 创建socker 连接请求 监听 关闭 开始 创建socker 绑定 关闭
创建socker 客户机
绑定 通 信
四、程序源代码及注释
服务器: #include <WINSOCK2.H> #include <stdio.h> #define PORT 6000 //服务器端口 #define MSGSIZE 1024 //收发缓冲区的大小 #pragma comment(lib, "ws2_32.lib") /*链接到WS2_32.lib,ws2_32.lib文 件,提供了对网络相关API的支持*/ DWORD WINAPI FunThread(LPVOID); //创建一个线程,专门用来接收 数据 /*填充sockaddr_in结构,此数据结构用做bind、connect、recvfrom、 sendto等函数的参数,指明地址信息*/ SOCKET sListen; //监听套接字 SOCKET sClient; SOCKADDR_IN client; //保存客户的地址信息 int iaddrSize = sizeof(SOCKADDR_IN); int main() { WSADATA wsaData;/*这个结构被用来存储 被WSAStartup函数调用后 返回的 Windows Sockets数据*/ char s_Message[MSGSIZE]; //收发缓冲区
WSAStartup(0x0202, &wsaData); /*调用全局函数;即WSA(Windows SocKNDs Asynchronous,Windows异步套接字)的启动命令;第一个参 数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字 节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信 息,第二个参数指向WSADATA数据结构的指针*/ sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);/*第一个 参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参 数置AF_INET; 第二个参数指定要创建的套接字类型,流套接字类型为 SOCK_STREAM、数据报套接字类型为SOCK_DGRAM、原始套接字 SOCK_RAW(WinSock接口并不适用某种特定的协议去封装它,而是由 程序自行处理数据包以及协议首部;第三个参数指定应用程序所使用的 通信协议。此参数可以指定单个协议系列中的不同传输协议。在Internet 通讯域中,此参数一般取值为0,系统会根据套接字的类型决定应使用 的传输层协议。该函数如果调用成功就返回新创建的套接字的描述符, 如果失败就返回INVALID_SOCKET*/ if(sListen == INVALID_SOCKET) { printf("Failed socket() \n"); return 0; } /*填充sockaddr_in结构,此数据结构用做bind、connect、recvfrom、 sendto等函数的参数,指明地址信息*/ SOCKADDR_IN local; local.sin_family = AF_INET; //AF_INET指明使用TCP/IP协议族 local.sin_port = htons(PORT);//指明连接服务器的端口号 local.sin_addr.s_addr = htonl(INADDR_ANY);//自动获取本机地址 if(bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN))==SOCKET_ERROR)/*第一个参数是一个套接 字。 第二个参数是一个sockaddr结构指针,该结构中包含了要结合的地 址和端口号,第三个参数确定sListen缓冲区的长度。返回值:如果函数 执行成功,返回值为0,否则为SOCKET_ERROR。 */ { printf("Failed bind() \n"); return 0; } if(listen(sListen, 1)==SOCKET_ERROR)/*第一个参数是一个已绑定未
被连接的套接字描述符,第二个参数是连接请求队列的最大长度(一般 由2到4)。用SOMAXCONN则由系统确定。返回值:无错误,返回0, 否则,返回SOCKET ERROR,可以调用函数WSAGetLastError取得错误 代码。*/ { printf("Failed listen() \n"); return 0; } sClient = accept(sListen,(struct sockaddr *)&client, &iaddrSize);/*服务程 序调用accept函数从处于监听状态的流套接字sListen的客户连接请求队 列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户 套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述 符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回 INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接 字;操作系统利用第二个参数来返回所连接的客户进程的协议地址(由 addr指针所指);操作系统利用第三个参数来返回该地址(参数二)的 大小 */ printf("Accepte client:%s:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));/*inet_ntoa 将一个IP转换成一 个互联网标准点分格式的字符串,ntohs将一个无符号短整形数从网络字 节顺序转换为主机字节顺序*/ HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);/*第一个参 数是指向安全属性的指针,NULL就行,第二个参数是初始线程堆栈大 小,0就可以,WINDOWS会自动分配,第三个参数指向线程函数,必须 是这样DWORD WINAPI ThreadProc (LPVOID pParam)第四个参数是传 给线程函数的参数,有就传,没有就NULL,第五个参数是线程启动方 式,可以是挂起CREATE_SUSPENDED,或者马上启动NULL,最后一个 参数是创建的线程ID。*/ CloseHandle(hThread); while (TRUE) { printf("Server Send:"); //从键盘输入 gets(s_Message); //发送数据
send(sClient, s_Message, strlen(s_Message), 0);/*向一个已连接的套接口 发送数据。sClient是一个用于标识已连接套接口的描述字。s_Message 包含待发送数据的缓冲区。strlen(s_Message)缓冲区中数据的长度。0调 用执行方式。*/ } return 0; } DWORD WINAPI FunThread(LPVOID)//接受线程函数 { char c_Message[MSGSIZE]; int ret; //接收字节的个数 while (TRUE) { ret = recv(sClient, c_Message, MSGSIZE, 0); /*从一个套接口接收数 据。sClient:一个标识已连接套接口的描述字。c_Message:用于接收 数据的缓冲区。MSGSIZE:缓冲区长度。0:指定调用方式。该函数返 回值是接收到的字节数*/ if(ret==SOCKET_ERROR) { printf("\nclient is closed!"); sClient = accept(sListen, (struct socka来自百度文库dr *)&client, &iaddrSize);//重新 开始监听 printf("\nAccepte new client:%s:%d", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); memset(c_Message,0,1024);//将原来的client message归零,将 c_Message中前1024个字节用0代替 continue; } c_Message[ret] = '\0'; printf("\nReceived: %s\n", c_Message); } return 0; } 客户端: #include <WINSOCK2.H> #include <stdio.h> #define SERVER_ADDRESS "127.0.0.1" //服务器端IP地址
#define PORT 6000 #define MSGSIZE 1024 #pragma comment(lib, "ws2_32.lib") /*链接到WS2_32.lib,ws2_32.lib文 件,提供了对网络相关API的支持*/ DWORD WINAPI FunThread(LPVOID); SOCKET sClient; SOCKADDR_IN server;//保存服务器的地址信息 int main() { WSADATA wsaData; /*这个结构被用来存储 被WSAStartup函数调 用后返回的 Windows Sockets数据*/ char c_Message[MSGSIZE]; //收发缓冲区 WSAStartup(0x0202, &wsaData);/*调用全局函数;即WSA(Windows SocKNDs Asynchronous,Windows异步套接字)的启动命令;第一个参 数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字 节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信 息,第二个参数指向WSADATA数据结构的指针*/ sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); memset(&server, 0, sizeof(SOCKADDR_IN)); /*先将保存地址的server 置为全0*/ server.sin_family = PF_INET; //声明地址格式是TCP/IP地址格式 server.sin_port = htons(PORT); //指明连接服务器的端口号 server.sin_addr.s_addr = inet_addr(SERVER_ADDRESS); /*指明连接服 务器的IP地址*/ connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN)); /* 连到刚才指明的服务器上*/ HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);/*第一个参 数是指向安全属性的指针,NULL就行,第二个参数是初始线程堆栈大 小,0就可以,WINDOWS会自动分配,第三个参数指向线程函数,必须 是这样DWORD WINAPI ThreadProc (LPVOID pParam)第四个参数是传 给线程函数的参数,有就传,没有就NULL,第五个参数是线程启动方 式,可以是挂起CREATE_SUSPENDED,或者马上启动NULL,最后一个 参数是创建的线程ID。*/
一、设计目的和要求
1、实验目的 通过本次专业设计使学生更进一步掌握计算机网络编程的有关知 识(包括TCP报文格式,TCP通信过程),加深对计算机网络编程知识 的理解。 2、实验要求 设置服务器和客户机,通过建立TCP连接,实现服务器和客户机之 间相互通信。
二、设计说明
设计分析:服务器和客户机根据TCP协议建立连接,另外在服务器和客 户机端分别设置一个线程用于接收信息,以实现全双工通信。 系统运行环境:windows7操作系统,VS2010 设计中的重点和难点:理解TCP通信双方建立连接的过程
相关文档
最新文档