今天抽空看了一些简单的东西,主要是对服务器server和客户端client的简单实现。

面向连接的server和client,其工作流程如下图所示:

服务器和客户端将按照这个流程就行开发。。(个人觉得:通过这个流程图,Server应该要先于Client启动,不然Client的connect函数的执行就会出错啦,不知道我的个人感觉对不对,后面试试就知道了。。O(∩_∩)O~)

注意:上图的Server和Client的工作流程是基于面向有连接通信的工作流程,如果是无连接的通信,则不必调用listen和accept。 在无连接的通信中,Server调用recvfrom函数来接收消息

在编写服务器和客户端之前,需要对TCP状态有所了解。。在server和client通信之间,二者都是通过发送/接收不同的信号来改变自己的状态,其tcp状态转换图如下:

了解了二者的开发流程,就可以通过接口来具体实现。

简单的server代码实现:

 #include"winsock2.h"
#include<iostream>
using namespace std;
//This line is very important #pragma comment(lib,"ws2_32.lib")
int main()
{
WSADATA wsaData;
SOCKET ListeningSocket;
SOCKET NewConnection;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int ClientAddrLen;
int Port = ;
int Ret;
char DataBuffer[]; if ((Ret = WSAStartup(MAKEWORD(,), &wsaData)) != )
{
cout<<"WSAStartup failed with error "<<Ret<<endl;
//here no WSACleanup,because we do not create anything;
return -;
} // Create a new socket to listening for client connections.
ListeningSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( INVALID_SOCKET == ListeningSocket)
{
cout<<"Socket failed with error "<<WSAGetLastError()<<endl;
WSACleanup();
return -;
} ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(Port); //to bind
if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
{
cout<<"Binding failed with error "<<WSAGetLastError()<<endl;
closesocket(ListeningSocket);
WSACleanup();
return -;
} // Listen for client connections. We used a backlog of 5 which is
// normal for many applications. if (listen(ListeningSocket,) == SOCKET_ERROR)
{
cout<<"Listen failed with error "<<WSAGetLastError()<<endl;
closesocket(ListeningSocket);
WSACleanup();
return -;
} cout<<"** We are waiting for a connection on port "<<Port<<"**"<<endl; //accep a connection when one arrives NewConnection = accept(ListeningSocket,(SOCKADDR*)&ClientAddr,&ClientAddrLen);
if (INVALID_SOCKET == NewConnection)
{
cout<<"Accept failed with error "<<WSAGetLastError()<<endl;
closesocket(ListeningSocket);
WSACleanup();
return -;
} cout<<"** We successfully got a connection from "<<inet_ntoa(ClientAddr.sin_addr)
<<":port "<<ntohs(ClientAddr.sin_port)<<"!!**"<<endl; closesocket(ListeningSocket);
cout<<"** We are waiting for data...**\n"; Ret = recv(NewConnection,DataBuffer,sizeof(DataBuffer),);
if (SOCKET_ERROR == Ret)
{
cout<<"Recv failed with error "<<WSAGetLastError()<<endl;
closesocket(NewConnection);
WSACleanup();
return -;
} cout<<"**We have successfully recieve "<<Ret<<" Byte(s) data!**\n"; cout<<"**We are going to close the client connection...**\n"; closesocket(NewConnection);
WSACleanup(); return ;
}

Server Code

客户端的实现:

 #include"winsock2.h"
#include<iostream>
using namespace std;
//This line is very important #pragma comment(lib,"ws2_32.lib")
int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET s;
SOCKADDR_IN ServerAddr;
int Port = ;
int Ret; if (argc <= )
{
cout<<"USAGE: tcpclient <Server IP address>.\n";
return -;
} // Initialize Winsock version 2.2 if ((Ret = WSAStartup(MAKEWORD(,), &wsaData)) != )
{
cout<<"WSAStartup failed with error "<<Ret<<endl;
return -;
} // Create a new socket to make a client connection. s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == s)
{
cout << "socket failed with error " << WSAGetLastError()<<endl;
WSACleanup();
return -;
} ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = inet_addr(argv[]); // Make a connection to the server with socket s. cout<< "We are trying to connect to " << inet_ntoa(ServerAddr.sin_addr)
<< ":" << htons(ServerAddr.sin_port) << "...\n"; if (connect(s, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr))
== SOCKET_ERROR)
{
cout << "connect failed with error " << WSAGetLastError() << endl;
closesocket(s);
WSACleanup();
return -;
} cout << "Our connection succeeded.\n"; cout << "We will now try to send a hello message.\n"; if ((Ret = send(s, "Hello", , )) == SOCKET_ERROR)
{
cout << "send failed with error " << WSAGetLastError()<<endl;
closesocket(s);
WSACleanup();
return -;
} cout << "We successfully sent " << Ret << " byte(s).\n"; // When you are finished sending and receiving data on socket s,
// you should close the socket. cout << "We are closing the connection.\n"; closesocket(s); // When your application is finished handling the connection, call
// WSACleanup. WSACleanup();
return ;
}

Client Code

咦,奇了怪了,按照书上的代码,执行起来居然报错。。这是咋回事啊。。

运行Server时,出现这样的错误:

通过报错信息可以知道是accept函数出错了。

那就对症下药,哪儿错儿改哪儿。。

上网查找资料,找到accept函数定义:

SOCKET accept(
__in SOCKET s,
__out struct sockaddr *addr,
__inout int *addrlen
);

第一个参数就是套接字描述符,第二个参数是,接受客户端基本信息的结构体,第三参数很重要,是准备接受结构体的大小,上面的程序 int ClientAddrLen;传进去的时候只是把未知的ClientAddrLen的地址传进去,要传进去的应该是接收这些信息的基本大小啊,所以 得加ClientAddrLen = sizeof(SOCKADDR);。这样程序就执行accept。

注意:客户端需要在服务器运行的时候才能执行,不然会出错的。。

运行Server和Client(需要ip作为main函数的参数,不会的自己百度怎样在VS2008中给main传递参数),二者可以连接了。。执行还没有实现二者的通信。。。呜呜~~~~(>_<)~~~~

拓展:

观察Server中的recv函数和Client中send函数,我想是否可以利用无限循环的方式在Client端输入字符串,在Server端打印该字符串?----就像聊天一样,你输入一句,我这边就显示这一句。。。只是这样只能是单工方式的传输,不能从Server发送到Client端。。那是否可以考虑多线程呢,一个线程运行Server,一个线程运行Client。。??

Winsock网络编程笔记(2)----基于TCP的server和client的更多相关文章

  1. Fixed-Length Frames 谈谈网络编程中应用层(基于TCP/UDP)的协议设计

    http://blog.sina.com.cn/s/blog_48d4cf2d0101859x.html 谈谈网络编程中应用层(基于TCP/UDP)的协议设计 (2013-04-27 19:11:00 ...

  2. Winsock网络编程笔记(3)----基于UDP的server和client

    在上一篇随笔中,对Winsock中基于tcp面向连接的Server和Client通信进行了说明,但是,Winsock中,Server和Client间还可以通过无连接通信,也就是采用UDP协议.. 因此 ...

  3. Winsock网络编程笔记(1)----入门

    今天第一次接触winsock网络编程,看的资料是Windows网络编程第二版.通过博客记住自己的看书笔记.. 在这里贴出第一个程序,虽然程序什么都没做,但以此作为入门,熟悉其网络编程风格.. #inc ...

  4. Linux 系统编程 学习:008-基于socket的网络编程3:基于 TCP 的通信

    背景 上一讲我们介绍了 基于UDP 的通信 这一讲我们来看 TCP 通信. 知识 TCP(Transmission Control Protoco 传输控制协议). TCP是一种面向广域网的通信协议, ...

  5. 网络编程应用:基于TCP协议【实现对象传输】--练习

    要求: 基于TCP协议实现,客服端向服务器发送一个对象 服务器接受并显示用户信息 ,同时返回给客户端 "数据已收到" 建一个Student类,属性:name age Student ...

  6. 网络编程应用:基于TCP协议【实现文件上传】--练习

    要求: 基于TCP协议实现一个向服务器端上传文件的功能 客户端代码: package Homework2; import java.io.File; import java.io.FileInputS ...

  7. 网络编程应用:基于TCP协议【实现一个聊天程序】

    要求: 基于TCP协议实现一个聊天程序,客户端发送一条数据,服务器端发送一条数据 客户端代码: package Homework1; import java.io.IOException; impor ...

  8. Winsock网络编程笔记(4)----基本的理论知识

    前面的笔记记录了Winsock的入门编程,领略了Winsock编程的乐趣..但这并不能算是掌握了Winsock,加深理论知识的理解才会让后续学习更加得心应手..因此,这篇笔记将记录一些有关Winsoc ...

  9. Java基础知识强化之网络编程笔记13:TCP之TCP协议上传图片并给出反馈

    1. TCP协议上传图片并给出反馈: (1)客户端: package cn.itcast_13; import java.io.BufferedInputStream; import java.io. ...

随机推荐

  1. codeigniter 去除index.php (nginx,apache) 通用方法

    .htaccess文件配置 1 <IfModule mod_rewrite.c> 2 RewriteEngine On 3 RewriteBase / 4 RewriteCond $1 ! ...

  2. BZOJ2431_逆序对数列_KEY

    转自YXDs 题目传送门 不知道今天是怎么了,可能是空调吹多了吧,一直不在状态,连递推题我都做不来了--(扎Zn了老Fe--) 然而,不管环境如何恶劣,我们仍要努力学习,为了自己的明天而奋斗.(说的好 ...

  3. Glide 这样用,更省内存!!!

    一.前言 Glide 是 Google 官方推荐的一款图片加载库,使用起来也非常的简单便利,Glide 它帮我们完成了很多很重要,但是却通用的功能,例如:图片的加载压缩.展示.加载图片的内存管理等等. ...

  4. web.xml中servlet-mapping的配置

    <servlet-mapping>元素在Servlet和URL样式之间定义一个映射.它包含了两个子元素<servlet- name>和<url-pattern>,& ...

  5. PLSQL Developer 连接oracle(64)(instantclient_32)

    下载instantclient-basic-nt-11.2.0.2.0位客户端,加压后存放,如F:\instantclient_11_2 拷贝Oracle 11.2G的msvcr80.dll和tnsn ...

  6. ADALINE模型

    ADALINE模型即自适应线性单元(Adaptive Linear Neuron),主要用于信号处理中的自适应滤波.预测和模式识别.其结构图如下 输入向量X=(x0,x1,x2,...,xn)T每个输 ...

  7. Musical Theme poj1743(后缀数组)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16757   Accepted: 5739 De ...

  8. FPGA在AD采集中的应用

    AD转换,也叫模数转换,是将模拟信号转换为数字信号.目前包括电脑CPU,ARM,FPGA,处理的信号都只能是数字信号,所以数据信号在进入处理芯片前必须要进行AD转换. 在高速的AD转换中,FPGA以其 ...

  9. webpack2使用ch9-处理模板文件 .html .ejs .tpl模板使用

    1 目录展示 安装依赖 "ejs-loader": "^0.3.0","html-loader": "^0.4.5", ...

  10. jQuery form插件使用详解

    点击打开: jquery选择器全解 jquery中的style样式操作 jquery中的DOM操作 jquery中的事件操作全解 jquery中的动画操作全解 jquery中ajax的应用 自定义jq ...