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

服务器的代码

/*
 *  服务器端 Server.c
 *
 */
#pragma comment(lib,"ws2_32")
#include 
#include 
#include 

#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
#include
#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"<>sendData;
		if(strcmp(sendData,"quit") == 0)
		{
			break;
		}
		if(send(s_server,sendData,BUFFSIZE,0) == SOCKET_ERROR)
		{
			cout<<"消息发送失败"<

你可能感兴趣的:(计算机网络)