欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计算机网络课程设计——网络聊天程序的设计与实现

程序员文章站 2024-02-12 10:36:10
...

服务器的代码

/*
 *  服务器端 Server.c
 *
 */
#pragma comment(lib,"ws2_32")
#include <winsock2.h>
#include <stdio.h>
#include <string.h>

#define BUFFSIZE 1024

int main(int argc, char**argv)
{
    int             Ret; //赋予初始化之后的要赋予的值
    WSADATA         wsaData;  //初始化
    SOCKET          ListeningSocket; //监听客户机的套接字
    SOCKET          NewConnection; //建立连接的套接字
    SOCKADDR_IN     ServerAddr; //服务器端结构体
    SOCKADDR_IN     ClientAddr; //客户机端结构体
    int             ClientAddrLen = sizeof(ClientAddr);  //计算客户机断结构体的长度
    unsigned short  Port = 5000; //和客户机建立的端口,客户机也有一个端口号,两个端口号相同时才会建立连接,TCP/IP的端口号的范围在0-65535
    char            sendData[BUFFSIZE]; //传送的数据
    char            recvData[BUFFSIZE]; //接受的数据

	//第一步、初始化WinSock,调用WSAStarup接口函数就可以
    if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
        printf("WSASTARTUP_ERROR: %d\n", Ret);
        return 0;
    }

    //第二步、创建一个套接字来监听客户机连接,套接字socket包含了两个信息,一个是IP地址,一个是Port端口号,使用
	//这两个信息,就可以确定网路中的任何一个通讯节点。
	//socket三个参数的含义、第一个参数指定Socket类型(流式、数据报套接字)、第三个套接字是与特定的地址家族相关的协议(若指定为0,系统会自动选择一个合适的协议)
    if((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)//INVALID_SOCKET意思是无效套接字
    {
        printf("SOCKET_ERROR: %d\n", INVALID_SOCKET);
        return 0;
    }


    /*
     *第三步、 填充SOCKADDR_IN结构,这个结构将告知bind我们想要在5150端口监听所有接口上的连接
     */
    ServerAddr.sin_family = AF_INET; //sin_family字段必须设置为AF_INET,这是告诉WinSock使用的是IP地址族
    ServerAddr.sin_port = htons(Port); //将端口变量从主机字节顺序转换位网络字节顺序,必须要设置
	//IP地址(long)和port端口(short),转换成网络字节后才能用bind()函数绑定
    ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //用来通讯的IP地址


    //第四步、使用bind将这个地址信息和套接字绑定起来,包含了需要建立连接的本地的地址,包括地址组、IP和端口信息
	//int bind(SOCKET s,const stuct sockaddr FAR* name,int namelen)
    if(bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
    {
        printf("BIND_ERROR: %d\n", SOCKET_ERROR);
        return 0;
    }

    //第五步、监听客户机连接。这里使用5个backlog
    if(listen(ListeningSocket, 5) == SOCKET_ERROR)
    {
        printf("LISTEN_ERROR: %d\n", SOCKET_ERROR);
        return 0;
    }

    //第六步、连接到达时,接受连接
    printf("正在接受连接...");
    if((NewConnection = accept(ListeningSocket, (SOCKADDR *)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET)
    {
        printf("ACCPET_ERROR: %d\n", INVALID_SOCKET);
        closesocket(ListeningSocket);
        return 0;
    }
    printf("检测到一个连接: %s 端口:%d\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));

    //第七步、聊天
    while(true)
    {
        //接收数据
        Ret = recv(NewConnection, recvData, BUFFSIZE, 0);
        if(Ret > 0)
            printf("Client对你说: %s\n", recvData);
        else if(Ret < 0)
            printf("RECV_ERROR: %d\n",  SOCKET_ERROR);
        else
        {
            printf("对方退出程序,聊天结束!");
            break;
        }

        //发送数据
        printf("\nServer说:");
        scanf("%s", sendData);
        if(strcmp(sendData, "quit") == 0)   //退出
            break;
        if(send(NewConnection, sendData, BUFFSIZE, 0) == SOCKET_ERROR)
        {
            printf("消息发送失败!\n");
            break;
        }
    }
    //第八步、从容关闭
    shutdown(NewConnection, SD_BOTH);

    //完成新接受的连接后,用closesocket API关闭这些套接字
    closesocket(NewConnection);
    closesocket(ListeningSocket);

    //应用程序完成对接的处理后,调用WSACleanup
    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
        return 0;
    }

    system("pause");
    return 0;
}

客户端代码

/*
 *  客户端 Client.c
 *
 */
#include<iostream>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define BUFFSIZE 1024
int main()
{
	int Ret; //赋予初始化之后的要赋予的值
	char sendData[BUFFSIZE];//定义发送缓冲区和接受缓冲区
	char recvData[BUFFSIZE];

	SOCKET s_server;//定义服务端套接字,接受请求套接字

	SOCKADDR_IN server_addr;//服务端地址客户端地址

	//初始化套接字库
	WORD w_req=MAKEWORD(2,2);//版本号
	WSADATA wsadata;
	int err;
	err = WSAStartup(w_req,&wsadata);
	if(err!=0)
	{
		cout<<"初始化套接字库fail"<<endl;
	}
	else
	{
		cout<<"初始化套接字库success"<<endl;
	}

	//填充服务端信息
	server_addr.sin_family=AF_INET;
	server_addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	server_addr.sin_port=htons(5000);

	//创建套接字
	s_server=socket(AF_INET,SOCK_STREAM,0);
	//建立连接
	if(connect(s_server,(SOCKADDR *)&server_addr,sizeof(SOCKADDR))==SOCKET_ERROR)
	{
		cout<<"CONNECT_ERROR : "<<SOCKET_ERROR<<endl;
		return 0;
	}
	else
	{
		cout<<"服务器连接成功!"<<endl;
	}

	//发送,接收数据
	while(true){
		//发送数据
		cout<<'\n'<<"Client说:";
		cin>>sendData;
		if(strcmp(sendData,"quit") == 0)
		{
			break;
		}
		if(send(s_server,sendData,BUFFSIZE,0) == SOCKET_ERROR)
		{
			cout<<"消息发送失败"<<endl;
			break;
		}

		//接收数据
		Ret = recv(s_server,recvData,BUFFSIZE,0);
		if(Ret < 0)
		{
			cout<<"RECV_ERROR"<<SOCKET_ERROR<<endl;
			break;
		}
		else if(Ret == 0)
		{
			cout<<"对方退出聊天程序,聊天结束"<<endl;
			break;
		}
		else
		{
			cout<<"Server对你说:"<<recvData<<endl;
		}

	}
	//关闭套接字
	closesocket(s_server);
	//释放DLL资源
	WSACleanup();
	return 0;
}