关于socket的文章,园子里面有很多,其实无非就是 WSAStartup、socket、bind、listen、accept、recv、send(服务端),WSAStartup、socket、connect、send、recv(客户端)的使用。今天第一次看socket,也只学会了socket阻塞模式,即一个服务端对一个客户端,别的客户端想连接也连接不上--个人理解,不知道对不对。

为了解决一(服务端)对多(客户端)的问题,自作聪明在服务端用上了多线程。初步效果还不错:

我晕,1080P的笔记本上截的图,放上来这么大!

上代码,

TCPServer.cpp

 /****************************************************************************
/* 文 件 名:server.cpp *
/* 作 者:ZhangXuliang *
/* 日 期:2015/05/24 星期日 11:28 *
/* 版 本 号:V 1.0.0 *
/* 版权说明:Copyright(c)2015 ZXL. All rights reserved. *
/* 描 述:多线程处理Client连接 *
/****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include <iostream>
#include <windows.h>
#include <process.h> //#include <WinSock2.h>
#pragma comment(lib,"Ws2_32.lib") #define SERVER_IP "127.0.0.1"
#define SERVER_PORT 9999
#define BUFSIZE (1024) //定义一个结构体,存储客户端的sClient、sockaddr_in结构
typedef struct _ClientStruct
{
SOCKET csSocket;
SOCKADDR_IN csSockAddr_In;
} ClientStruct, *LPClientStruct; //处理后续客户端事件的程序
void ClientEven(PVOID param); using namespace std;
int main()
{
int ErrCode; //错误代码
int addrlen;
WSADATA WSAdata;
SOCKET sServer, sClient;
SOCKADDR_IN saServer, saClient; //初始化
ErrCode = WSAStartup(MAKEWORD(, ), &WSAdata);
if (ErrCode)
{
cout << "WSAStartup()出错!错误代码:#" << ErrCode << endl;
WSACleanup();
return -;
} //创建套接字
sServer = socket(AF_INET, SOCK_STREAM,);
if (INVALID_SOCKET == sServer)
{
cout << "socket()出错!错误代码:#" << WSAGetLastError() << endl;
WSACleanup();
return -;
} //初始化saServer
saServer.sin_family = AF_INET;
saServer.sin_addr.S_un.S_addr = htons(INADDR_ANY);
saServer.sin_port = htons(SERVER_PORT);
//绑定监听IP和端口,以便下面的listen()监听
ErrCode = bind(sServer, (SOCKADDR *)&saServer, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == ErrCode)
{
cout << "bind()出错!错误代码:#" << WSAGetLastError() << endl;
WSACleanup();
return -;
} //开始监听
ErrCode = listen(sServer, );
if (SOCKET_ERROR == ErrCode)
{
cout << "listen()出错!错误代码:#" << WSAGetLastError() << endl;
WSACleanup();
return -;
}
cout << "正在监听端口:" << SERVER_PORT << endl; while (TRUE)
{
//接受来自客户端的连接请求
addrlen = sizeof(saClient);
sClient = accept(sServer, (SOCKADDR *)&saClient, &addrlen);
if (INVALID_SOCKET == sClient)
{
cout << "accpet()出错!错误代码:#" << WSAGetLastError() << endl;
} //启动一个线程,来处理后续的客户端事件
LPClientStruct lpcsClient = new ClientStruct; //个人觉得这儿用 new 是一个创举啊,因为在启动线程后,如果直接将ClientStruct指针
lpcsClient->csSocket = sClient; //传到ClientEven()中,那么,当有中一个Client接入时,会改变ClientEven中的ClientStruct内容
lpcsClient->csSockAddr_In = saClient; //所以这儿用new,再在线程中delete
_beginthread(ClientEven,, lpcsClient); }
WSACleanup();
return ;
} void ClientEven(PVOID param)
{
int ErrCode; char buf[BUFSIZE] = { };
SYSTEMTIME time;
GetLocalTime(&time);
sprintf(buf, "%4d-%02d-%02d %02d:%02d:%02d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond); //设置下输出的字体的颜色
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
cout << buf << "\t" << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":"
<< ((LPClientStruct)param)->csSockAddr_In.sin_port << "\t接入服务器" << endl;
//还原字体颜色
SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
//连接成功,先发送一条成功的消息
ErrCode = send(((LPClientStruct)param)->csSocket, "连接服务器成功", strlen("连接到服务器成功!"),);
if (SOCKET_ERROR == ErrCode)
{
cout << "send()出错!错误代码:#" << WSAGetLastError() << endl;
delete (LPClientStruct)param;
_endthread();
} while (TRUE)
{
//接受消息
ZeroMemory(buf, BUFSIZE);
ErrCode = recv(((LPClientStruct)param)->csSocket, buf, sizeof(buf), );
if (SOCKET_ERROR == ErrCode)
{
if (WSAGetLastError() == )
{
SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
cout << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":" << ((LPClientStruct)param)->csSockAddr_In.sin_port << "\t被强制断开连接!" << endl;
SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
}
else
{
cout << "recv()出错!错误代码:#" << WSAGetLastError() << endl;
} delete (LPClientStruct)param; //退出线程之前先delete前面new的ClientStruct
_endthread();
} cout << inet_ntoa(((LPClientStruct)param)->csSockAddr_In.sin_addr) << ":" << ((LPClientStruct)param)->csSockAddr_In.sin_port << "\t说:" << buf << endl; //反馈消息
//if ((pPipe = _popen(buf, "rt")) != NULL)
//{
// while (!feof(pPipe))
// {
// fgets(szResult, 32, pPipe);
// strcat(buf, szResult);
// if (strlen(buf) == 1024)
// {
// buf[1024] = 'c'; //c --continue
// send(((LPClientStruct)param)->csSocket, buf, sizeof(buf), 0);
// ZeroMemory(buf, BUFSIZE);
// }
// }
// _pclose(pPipe);
//}
//else
// strcpy(buf, "打开匿名管道失败!"); ErrCode = send(((LPClientStruct)param)->csSocket, buf, sizeof(buf), ); if (SOCKET_ERROR == ErrCode)
{
cout << "send()出错!错误代码:#" << WSAGetLastError() << endl; delete (LPClientStruct)param; //退出线程之前先delete前面new的ClientStruct
_endthread();
}
}
delete (LPClientStruct)param; //退出线程之前先delete前面new的ClientStruct
_endthread();
}

下面是TCPClient.cpp

 /****************************************************************************
/* 文 件 名:Client.cpp *
/* 作 者:ZhangXuliang *
/* 日 期:2015/05/23 星期六 23:30 *
/* 版 本 号:V 1.0.0 *
/* 版权说明:Copyright(c)2015 ZXL. All rights reserved. *
/* 描 述:Client客户端 *
/****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include <iostream>
#include <string> #include <winsock.h>
#pragma comment(lib,"ws2_32.lib") using namespace std; #define BUFSIZE 1024
#define PORT 9999
//#define SERVER_IP "127.0.0.1" int main()
{
WSAData wsaData;
SOCKET sHost;
sockaddr_in addrServ;
char buf[BUFSIZE];
int retVal; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
{
cout << "WSAStartup()失败!" << endl;
return -;
} sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sHost)
{
cout << "socket()出错!" << endl;
WSACleanup();
return -;
} addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(PORT);
addrServ.sin_addr.S_un.S_addr = inet_addr("192.168.1.223"); retVal = connect(sHost, (LPSOCKADDR)&addrServ, sizeof(addrServ));
if (SOCKET_ERROR == retVal)
{
cout << "connect()出错!" << endl;
closesocket(sHost);
WSACleanup();
return -;
}
retVal = recv(sHost, buf, sizeof(buf) + , );
cout << "从服务器接受:" << buf << endl << endl << endl;
while (TRUE)
{
cout << "输入要发给服务器的内容:";
//string msg;
//getline(cin.msg);
char msg[BUFSIZE];
//cin.getline(msg, BUFSIZE);
cin >> msg;
//cout << endl;
ZeroMemory(buf, BUFSIZE);
strcpy(buf, msg); retVal = send(sHost, buf, strlen(buf), );
if (SOCKET_ERROR == retVal)
{
cout << "发送失败!" << endl;
closesocket(sHost);
WSACleanup();
return -;
} retVal = recv(sHost, buf, sizeof(buf) + , );
if (SOCKET_ERROR == retVal)
{
cout << "recv()出错!错误代码:#" << WSAGetLastError() << endl;
closesocket(sHost);
WSACleanup();
return -;
}
cout << "从服务器接受:" << buf << endl << endl; if (strcmp(buf, "quit") == )
{
cout << "quit" << endl;
break;
}
} closesocket(sHost);
WSACleanup(); return ; }

windows下socket学习(一)的更多相关文章

  1. c++ 网络编程(四) LINUX/windows下 socket 基于I/O复用的服务器端代码 解决多进程服务端创建进程资源浪费问题

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613861.html 好了,继上一篇说到多进程服务端也是有缺点的,每创建一个进程就代表大量的运 ...

  2. windows下搭建学习objective-c 的运行环境【转载】

    对于Iphone开发学习者而言,Object -c 是必修的语言.但是由于苹果的自我封闭的产业链发展模式(从芯片.机器.开发语言.终端产品.服务)的限制,要想开发针对苹果iPhone等产品的应用程序, ...

  3. windows下Socket链接溢出

    最近在windows下使用通过多线程使用jdbc操作数据库,在线程数设置为5,并且每个线程执行完成后Sleep(1000),在这种情况下,竟然还会报错: java.net.SocketExceptio ...

  4. 使用Codeblock搭建Windows下Objec-c学习环境

    学习Object-c如果使用的是Windows,一般推荐使用虚拟机,但是太重量级了,先要下载OS-X,又要下载x-code.这里推荐一种比较简便的方式,使用code-block来搭建简易的Object ...

  5. node.js在windows下的学习笔记(3)---npm

    1.什么是npm npm是Node.js的包管理器,它允许开发人员在Node.js的应用程序中创建,共享,重用模块.之前我们通过node的官网的安装程序安装了Node.js,那么npm就已经装好了的. ...

  6. windows下socket编程:区分shutdown()及closesocket()

    以下描述主要是针对windows平台下的TCP socket而言. 首先需要区分一下关闭socket和关闭TCP连接的区别,关闭TCP连接是指TCP协议层的东西,就是两个TCP端之间交换了一些协议包( ...

  7. windows下socket编程实现client和server双向通信

    服务端代码server.c // server.cpp : Defines the entry point for the console application. // #include <s ...

  8. detours编译与windows下makefile学习

    1.编译 windows环境命令行编译很少用,detours需要使用命令行编译,刚好试试,过程如下: 1.为了能够在所有目录中使用nmake命令,需要设置环境变量Path D:\Program Fil ...

  9. node.js在windows下的学习笔记(9)---文件I/O模块

    开发中我们经常会有文件I/O的需求,node.js中提供一个名为fs的模块来支持I/O操作,fs模块的文件I/O是对标准POSIX函数的简单封装. 1.将"hello world" ...

随机推荐

  1. JVM内存格局总结

    最近一次面试,面试官让我讲讲JVM的内存这一块的理解.我回答的不满意,今天做一个总结. 做一个产品,最终要做到高并发.高可靠.归根结底,是对CPU.内存等资源受限所作出的解决方案.就内存而言,我们写的 ...

  2. [moka同学笔记]Yii2 数据操作Query Builder

    Query Builder [php] view plain copy   $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name ...

  3. Java一步一步构建web系统 在IDEA下用Maven搭建多模块项目

    1.需求 做一个项目会有很多模块,主要是方便复用,通过各个模块之间聚合.模块也可以独立出来,如公用类库,也可以在做其它项目中使用.该文的实例会有两个模块:分别为dallin-web模块,dallin- ...

  4. android 6.0添加权限

        @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissio ...

  5. ShareDrop – 苹果 AirDrop 服务的 HTML5 实现

    ShareDrop 是苹果 AirDrop 服务的 HTML5 版本,你可以直接在设备之间传输文件,而无需先上传到任何服务器.它使用 WebRTC 来实现安全的点对点文件传输.目前 ShareDrop ...

  6. WPF中的Invoke

    今天帮同事看一个问题,她用为了实现动画效果用主线程执行Thread.Sleep,然后界面就卡死了. 这个问题好解决,new 一个Thread就行了,但是更新WPF的界面需要主线程的操作,然后习惯性的打 ...

  7. SQLMAP使用笔记

    -u #注入点-f #指纹判别数据库类型-b #获取数据库版本信息-p #指定可测试的参数(?page=1&id=2 -p “page,id”)-D “” #指定数据库名-T “” #指定表名 ...

  8. 在iOS开发过程中你遇到这个问题了么?

    1.问题:加载UIWebView底部有黑色边框问题. 设置UIWebView opaque为NO,然后设置其背景色为clearColor. 2.问题:iPhone真机输出[UIScreen mainS ...

  9. 【代码笔记】iOS-点击城市中的tableView跳转到旅游景点的tableView,下面会有“显示”更多。

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...

  10. 【代码笔记】iOS-单项选择框

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...