server端双线程的tcp socket (阻塞)实验

 

在server端创建一个接收线程,一个发送线程

client端依旧单线程

 server.cpp

// Thread.cpp : 定义控制台应用程序的入口点。
//
  
//#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define buf_size 30
  
  
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
  
//创建线程
DWORD WINAPI Recv (LPVOID ipParameter)
{
    SOCKET clientSocket  = (SOCKET)ipParameter;
    int RET =  0;
    char RecvBuffer[buf_size];
    //初始化 recvBuffer
    while(true){
    memset(RecvBuffer,0x00,sizeof(RecvBuffer));
    RET  =  recv(clientSocket,RecvBuffer,buf_size,0);
    if(RET == 0||RET == SOCKET_ERROR)
    {
        cout<<"客户端退出"<<endl;
        break;
    }
    cout<<"接受的消息为"<<RecvBuffer<<endl;
    }
  
    return 0;  
}
//发送函数
DWORD WINAPI Send (LPVOID ipParameter)
{
    SOCKET clientSocket  = (SOCKET)ipParameter;
    int RET =  0;
    char SendBuffer[buf_size];
    //初始化 recvBuffer
    while(true){
    memset(SendBuffer,0x00,sizeof(SendBuffer));
	gets(SendBuffer);
    RET  =  send(clientSocket,SendBuffer,buf_size,0);
    if(RET == 0||RET == SOCKET_ERROR)
    {
        cout<<"客户端退出"<<endl;
        break;
    }
    cout<<"发送的消息为"<<SendBuffer<<endl;
    }
  
    return 0;  
}
int main(void)
{
    WSADATA     WSA;
    SOCKET      severScoket,clientSocket;
    struct      sockaddr_in  LocalAddr,clientAddr;
    int         AddrLen =  0;
    HANDLE      hThread1 =  NULL;
    HANDLE      hThread2 =  NULL;
    int         RET = 0;
    //init windows socket
    if (WSAStartup(MAKEWORD(2,2),&WSA)!= 0 )
    {
        cout<<"init failed"<<endl;
        return -1;
    }
    //creat socket
    severScoket = socket(AF_INET,SOCK_STREAM,0);
    if(severScoket == INVALID_SOCKET)
    {
        cout<<"creat failed"<<GetLastError()<<endl;
        return -1;
    }
    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    LocalAddr.sin_port = htons(PORT);
    memset(LocalAddr.sin_zero,0x00,8);
    //bind socket
    RET = bind(severScoket,(struct sockaddr*)&LocalAddr,sizeof(LocalAddr));
    if (RET != 0)
    {
        cout<<"bind failed";
        return -1;
    }
    RET = listen(severScoket,5);
    if (RET!= 0)
    {
        cout<<"listen failed";
        return -1;
    }
    cout<<"服务器已启动"<<endl;
    while(true)
    {
       AddrLen = sizeof(clientAddr);
       clientSocket = accept(severScoket,(struct sockaddr*)&clientAddr,&AddrLen);
       if (clientSocket ==INVALID_SOCKET)
       {
           cout<<"accept failed";
           break;
       }
       cout<<"客户端连接"<<inet_ntoa(clientAddr.sin_addr)<<"."<<clientAddr.sin_port<<endl;
       hThread1  = CreateThread(NULL,0,Recv,(LPVOID)clientSocket,0,NULL);
       if(hThread1 == NULL)
       {
           cout<<"creat thread failed"<<endl;
           break;
       }
       CloseHandle(hThread1);
	   hThread2  = CreateThread(NULL,0,Send,(LPVOID)clientSocket,0,NULL);
	   if(hThread2 == NULL)
	   {
		   cout<<"creat thread failed"<<endl;
		   break;
	   }
	   CloseHandle(hThread2);
    }
    closesocket(severScoket);
    closesocket(clientSocket);
    WSACleanup();
    return 0;
}

client.cpp

//#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define buf_size 30
  
  
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
int main(void)
{
    WSADATA     WSA;
    SOCKET      clientSocket;
    struct      sockaddr_in  serveAddr;
    int         AddrLen =  0;
    HANDLE      hThread =  NULL;
    int         RET = 0;
    char        SendBuffer[buf_size];
    char        RecvBuffer[buf_size];
    //init windows socket
    if (WSAStartup(MAKEWORD(2,2),&WSA)!= 0 )
    {
        cout<<"init failed"<<endl;
        return -1;
    }
    //creat socket
    clientSocket = socket(AF_INET,SOCK_STREAM,0);
    if(clientSocket == INVALID_SOCKET)
    {
        cout<<"creat failed"<<GetLastError()<<endl;
        return -1;
    }
    serveAddr.sin_family = AF_INET;
    serveAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    serveAddr.sin_port = htons(PORT);
    memset(serveAddr.sin_zero,0x00,8);
  
    RET = connect(clientSocket,(struct sockaddr*)&serveAddr,sizeof(serveAddr));
    if (RET != 0)
    {
        cout<<"connect failed";
        return -1;
    }
    else{ cout<<"连接成功"<<endl;}
    while(true)
    {
		ZeroMemory(SendBuffer,sizeof(SendBuffer));
		
        gets(SendBuffer);
        RET = send(clientSocket,SendBuffer,buf_size,0);
        if (RET == SOCKET_ERROR)
        {
            cout<<"send to error"<<endl;
            break;
        }
		cout<<"发送的消息为:"<<SendBuffer<<endl;

		ZeroMemory(RecvBuffer,sizeof(RecvBuffer));
		RET = recv(clientSocket,RecvBuffer,buf_size,0);
		if (RET == SOCKET_ERROR)
        {
            cout<<"recv error"<<endl;
			closesocket(clientSocket);
			WSACleanup();
			return -1;
           // break;
        }
			cout<<"接收的消息为:"<<RecvBuffer<<endl;

    }
    closesocket(clientSocket);
    WSACleanup();
    return 0;
}

实验效果:

一个发送和接收是一个轮回。如果连续两次发送,那么对方必须要到第二轮回时候才能将缓冲器文本打印出来

for example:

现在服务端连续发送两次,如上所说,客户端要到第二次轮回才能显示服务器第二次发送的内容

客户端还未按回车前的状态:

按了回车后:

 

转载于:https://my.oschina.net/u/3331172/blog/1827783

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值