计算机网络第四次实验

计算机网络第四次实验

实验名称

聊天程序设计

实验目的

熟练掌握socket编程命令,设计一个双人聊天程序。

Socket的详细介绍:http://t.csdnimg.cn/53Lr3

源码

客户端.cpp

#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <process.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

void ThreadReceive(PVOID param);
void SendReceiveException(int e);

SOCKET ClientSocket = INVALID_SOCKET;
char name[18] = "";

int main(void)
{
	system("title Client V1.4");
	system("mode con cols=60 lines=23");
	system("color 9F");
	SOCKADDR_IN ServerAddr = { 0 };
    WSADATA wsaData = { 0 };
    USHORT uPort = 47168;//服务端端口

    if (WSAStartup(MAKEWORD(2, 2), &wsaData))
    {
        printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }
    
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        printf("wVersion was not 2.2\n");system("pause");
        return -1;
    }

    ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ClientSocket == INVALID_SOCKET) {
        printf("socket failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }

	//服务器地址:127.0.0.1
	char IP[20] = "127.0.0.1";
	
    printf("请输入你的昵称:");
    gets(name);
    
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(uPort);
    ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP);

    printf("\n正在等待对方链接,请稍等...\n");
    if (SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))) { 
        printf("connect failed with error code: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        MessageBox(NULL,TEXT("链接服务器失败!"),TEXT("Error"),MB_OK|MB_ICONWARNING);
        return -1;
    }else{
    	printf("链接成功...\n\n\n");
	} 

    char buffer[1024] = {0};
    int iRecvLen = 0;
    int iSnedLen = 0;

	_beginthread(ThreadReceive, 0, NULL); //启动线程

    iSnedLen = send(ClientSocket, name, strlen(name), 0);
    SendReceiveException(iSnedLen);
	
    while (1)
    {
        memset(buffer, 0, sizeof(buffer));
		printf("My:"); gets(buffer);
        iSnedLen = send(ClientSocket, buffer, strlen(buffer), 0);
        SendReceiveException(iSnedLen);
    }

    closesocket(ClientSocket);
    WSACleanup();
    printf("\n通讯结束!\n");
    system("pause");
    return 0;
}

void ThreadReceive(PVOID param)
{
	char buffer[1024] = {0};
    int iRecvLen = 0;
	
    char nameOther[32] = { 0 };
    iRecvLen = recv(ClientSocket, nameOther, sizeof(nameOther), 0);
    SendReceiveException(iRecvLen);
    strcat(nameOther, "\0");
    
    while(true)
    {
    	memset(buffer, 0, sizeof(buffer));
    	iRecvLen = recv(ClientSocket, buffer, sizeof(buffer), 0);
    	SendReceiveException(iRecvLen);
    	strcat(buffer, "\0");
    	printf("\r        \r【%s】:%s", nameOther,buffer);
    	printf("\nMy:");
	}
}

void SendReceiveException(int e)
{
	if(SOCKET_ERROR == e)
	{
		printf("\n\nsend failed with error code: %d\n", WSAGetLastError());
		printf("提示:链接异常或对方可能断开了链接!\n\n");
        closesocket(ClientSocket); //关闭客户端套接字 
        WSACleanup(); //释放DLL 
        MessageBox(NULL,TEXT("链接异常或对方可能断开了链接!"),TEXT("提示"),MB_OK|MB_ICONWARNING);
        system("pause"); 
        exit(-1);
	}
}

服务端.cpp

#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <process.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

typedef struct Client{
	SOCKET ServerSocket;
	SOCKET ClientSocket01;
	SOCKET ClientSocket02;
}CLS;

int init(CLS *pSer);
void CreatSocket(CLS *pcls);
void ThreadStart(CLS *pcls);
unsigned __stdcall ThreadReceive01(void* pCls);
unsigned __stdcall ThreadReceive02(void* pCls);
bool SendReceiveException(int e, CLS *p);

char Tempbuffer1[1024] = {0};
char Tempbuffer2[1024] = {0};

int main(void)
{
	system("title Server V1.3");
	system("color 1E");
	
	CLS cls;
    CLS *pcls = &cls;
	while(true)
	{
		init(pcls);
		CreatSocket(pcls);
		ThreadStart(pcls);
	} 

	while(true); 
	
    closesocket(pcls->ClientSocket01);
    closesocket(pcls->ClientSocket02);
    closesocket(pcls->ServerSocket);
    WSACleanup();
    return 0;
}

int init(CLS *pSer)
{
	SOCKADDR_IN ServerAddr = { 0 };
	pSer->ServerSocket = INVALID_SOCKET;
	USHORT uPort = 47168;
    WSADATA wsaData = { 0 };
    
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)){
        printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }
    
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
        printf("Version was not 2.2\n");
		MessageBox(NULL,TEXT("Version was not 2.2(version Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING);
		system("pause");
        return -1;
    }
    
    pSer->ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    if (pSer->ServerSocket == INVALID_SOCKET) {
        printf("socket failed with error code: %d\n", WSAGetLastError());
		MessageBox(NULL,TEXT("The initialization server failed!(socket function Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING);
		system("pause");
        return -1;
    }

    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(uPort);//服务器监听端口
    ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    if (SOCKET_ERROR == bind(pSer->ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))){
        printf("bind failed with error code: %d\n", WSAGetLastError());
        closesocket(pSer->ServerSocket);system("pause");
        return -1;
    }
    
    if (SOCKET_ERROR == listen(pSer->ServerSocket, 3))
    {
        printf("listen failed with error code: %d\n", WSAGetLastError());
        closesocket(pSer->ServerSocket);
        WSACleanup();system("pause");
        return -1;
    }
	else{
	return 0;
	}
} 

void CreatSocket(CLS *pcls)
{
    pcls->ClientSocket01 = INVALID_SOCKET;
    pcls->ClientSocket02 = INVALID_SOCKET;
    SOCKADDR_IN ClientAddr01 = { 0 };
    SOCKADDR_IN ClientAddr02 = { 0 };

    printf("\nwaiting connect.....\n\n");
    
	int ClientAddrLength01 = sizeof(ClientAddr01);
	int ClientAddrLength02 = sizeof(ClientAddr02);
	
    pcls->ClientSocket01 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr01, &ClientAddrLength01);//等待客户端1链接... 
    printf("Client01 link to success, wait for Client02 link...\n");
    pcls->ClientSocket02 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr02, &ClientAddrLength02);//等待客户端2链接... 
    printf("Client02 link to success,Start connect.\n\n");
    if (pcls->ClientSocket01 == INVALID_SOCKET || pcls->ClientSocket02 == INVALID_SOCKET) {
        printf("accept failed with error code: %d\n", WSAGetLastError());
        closesocket(pcls->ServerSocket);
        WSACleanup();//释放dll资源 
        MessageBox(NULL,TEXT("接收两个客户端出错,请重启服务器!"),TEXT("Error"),MB_OK|MB_ICONWARNING);
        exit(-1);
    }
}

void ThreadStart(CLS *pcls)
{
	HANDLE hThread01;
	HANDLE hThread02;
    unsigned threadID01;unsigned threadID02;
    
	printf("双方连接成功,开始聊天...\n\n"); 
	
    hThread01 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive01, pcls, 0, &threadID01 );
    
    hThread02 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive02, pcls, 0, &threadID02 );
    WaitForSingleObject(hThread01, INFINITE);
    WaitForSingleObject(hThread02, INFINITE);
	CloseHandle(hThread01);
	CloseHandle(hThread02);
}

//线程1-客户端01 
unsigned __stdcall ThreadReceive01(void* pCls)
{
	int isError = 0;
	bool flag = true;
	CLS *p = (CLS*)pCls;
	
	char name[20] = { 0 };
    isError = recv(p->ClientSocket01, name, sizeof(name), 0);
	if(SendReceiveException(isError, p))flag=false;
	
    isError = send(p->ClientSocket02, name, strlen(name), 0);
    if(SendReceiveException(isError, p))flag=false;
    printf("用户:%s---上线\n\n",name);

	while(flag)
	{
		memset(Tempbuffer1, 0, sizeof(Tempbuffer1));
		
    	isError = recv(p->ClientSocket01, Tempbuffer1, sizeof(Tempbuffer1), 0);
    	if(SendReceiveException(isError, p))flag=false;
    	strcat(Tempbuffer1, "\0");
    	printf("【%s】:%s\n",name,Tempbuffer1);
        isError = send(p->ClientSocket02, Tempbuffer1, strlen(Tempbuffer1), 0);
        if(SendReceiveException(isError, p))flag=false;
	}
}

//线程2-客户端02
unsigned __stdcall ThreadReceive02(void* pCls)
{
	int isError = 0;
	bool flag = true; //判断错误
	CLS *p = (CLS*)pCls;
	
	// 接收客户端02的用户名 
	char name[20] = { 0 };
    isError = recv(p->ClientSocket02, name, sizeof(name), 0);
	if(SendReceiveException(isError, p))flag=false;
	
    isError = send(p->ClientSocket01, name, strlen(name), 0);
    if(SendReceiveException(isError, p))flag=false;
    printf("用户:%s---上线\n\n",name);
    
	while(flag)
	{
		memset(Tempbuffer2, 0, sizeof(Tempbuffer2));
		
    	isError = recv(p->ClientSocket02, Tempbuffer2, sizeof(Tempbuffer2), 0);
    	if(SendReceiveException(isError, p))flag=false;
    	strcat(Tempbuffer2, "\0");
    	printf("【%s】:%s\n",name,Tempbuffer2);
    	
        isError = send(p->ClientSocket01, Tempbuffer2, strlen(Tempbuffer2), 0);
        if(SendReceiveException(isError, p))flag=false;
	}
}

bool SendReceiveException(int e, CLS *p)
{
	if(SOCKET_ERROR == e)
	{
		printf("send failed with error code: %d\n", WSAGetLastError());
        closesocket(p->ServerSocket);
        closesocket(p->ClientSocket01);
        closesocket(p->ClientSocket02);
        
        printf("\nException function:User disconnected or error,Close all Sockets!But no DLL file is freed.\n");

       	return true;
	}
	return false;
}

运行结果

在这里插入图片描述

说明:

该实验是利用Socket实现双人网络通信。

**服务端:**负责转发双方的消息,接收客户端A的消息,并转发给客户端B;接收客户端B的消息,并转发给客户端A。

**客户端:**接收对方的消息,发送消息给对方。

**关于线程:**服务端与客户端均使用了线程,在客户端中主线负责我方发送消息,另一个线程(函数名:ThreadReceive)用于接收对方的消息并显示在控制台。

参考http://t.csdnimg.cn/fDJOE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瓶瓶瓶瓶瓶^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值