今天抽空看了一些简单的东西,主要是对服务器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. java 如何将方法作为传参--多态

    在前段时研究智能算法时,发现如果使用java进行实现的话,往往具体实现过程差不多,但是适应值函数却根据 研究对象的不同发生很大的改变,这样对代码的维护产生很大的阻碍,于是产生的一个疑问:可不可以将适 ...

  2. mongoDB学习手记2--建库、删库、插入、更新

    上一篇  讲了在windows系统下的安装和启动,本文主要讲怎么建库.删库.插入.更新 在讲之前我们说一下mongoDB的一些基本概念,我们对比关系型数据库能更直观的理解 SQL术语/概念 Mongo ...

  3. 初识 JShell

    Java9 现在吵得热火朝天,赶紧顺势学习一波喽! JDK9 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk9-dow ...

  4. H5页面解决IOS进入不自动播放问题(微信内)

    废话少说,直接上代码. 主要还是调用微信的jdk做兼容处理.,安卓可自动播放. ($(function(){ $(function(){ /* ** 复选框*/ $('.ul-radio').on(' ...

  5. 数据分析前戏:ipython使用技巧(上)

    不一定非得使用Jupyter Notebook,试试ipython命令行 安装 ipython 我只试过Windows 10环境下的. 1.安装python安装包之后,应该就有ipython了. 2. ...

  6. 【POJ】2348 Euclid's Game(扩欧)

    Description Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first pl ...

  7. java基础(Fundamental)

    第一节 java开发环境 1.Linux操作系统 1)开源的操作系统.免费,主要作为服务器操作系统, 而Java主要是服务器端开发,所以部署环境都是Linux 2)Linux与Windows目录结构的 ...

  8. redis的发布订阅模式pubsub

    前言 redis支持发布订阅模式,在这个实现中,发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端),而是将信息发送给频道(channel),然后由频道将信息转发给所有对这个 ...

  9. KMP算法的细节问题

    preface: 想必,很多人都知道D.E.Knuth与V.R.Pratt和J.H.Morris同时提出所谓的狂拽酷炫屌炸天的KMP算法,在对字符串的匹配(或是字符串的查找)方面表现出比较好的效率,该 ...

  10. python xml sendEmail

    使用python进行发送邮件,研究的主要是用smtplib这个包,具体代码如下,eg: #!/usr/bin/python #coding=utf-8 import smtplib from emai ...