建立客户端的 Socket:

客户端应用程序首先也是调用 WSAStartup() 函数来初始化 Winsock 的动态连接库,然后同样

调用 socket() 来建立一个 TCP 或 UDP Socket(相同协议的Socket 才能相遇,TCP 对 TCP,UDP 对 UDP)。

与服务器的 Socket 不同的是,客户端的 Socket 可以调用 bind() 函数,来指定 IP 地址及端口号 port。

但也可以不调用 bind() 函数。而由 Winsock 来自动设定 IP 地址及端口号 port。

发起连接申请:

当客户端程序需要连接服务器时,客户端程序的 Socket 调用 connect() 函数监听,与 name 所指定的计算机的特定

端口上的服务器端 Socket 进行连接。函数调用成功返回 0,否则返回 SOCKET_ERROR。

connect() 函数原型

int connect(

    SOCKET s,          // 客户端流套接字

    const struct sockaddr FAR *name,  // 要连接的套接字的地址结构。

    int namelen        // 指明套接字的地址结构的长度。

);

函数示例:

//...

     struct sockaddr_in name;

     name.sin_family = FA_INET;

     name.sin_port = htons();

     name.sin_addr.s_addr = inet_addr("127.0.0.1");

     connect(sSocket,(struct sockaddr *)&name,sizeof(name));

//...

inet_addr() 可以用来转化字符串,主要用来将一个十进制的数转化为二进制数,多用于 IPv4 的 ip 转化。

返回:若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE。

用 Socket 实现数据的传送:

服务器和客户端分别创建 Socket 并连接后,就开始数据的传递。网络编程数据传送涉及两大协议:TCP/IP 和 UDP 协议。

Stream (TCP) Socket:提供双向,可靠,有次序,不重复的资料传送。

Datagram (UDP) Socket:虽然提供双向的通信,但是没有 可靠,有次序,不重复的保证,

所以 UDP 传送数据可能收到无次序,重复的资料,甚至资料在传输过程中会泄露。

一般情况下 TCP Socket 的数据发送和接收是调用 send() 和 recv() 这两个函数来完成的,

而 UDP Socket 则是调用 sendto() 和 recvfrom() 这两个函数,这两个函数调用成功返回发送或接收的资料长度,

否则返回 SOCKET_ERROR。

send() 函数原型:

int send(

    SOCKET s,          // 指定发送端套接字描述符。

    const char FAR *buf,  // 指明一个存在应用程序要发送数据的缓冲区。

    int len,      // 指明实际要发送的数据的字节数。

    int flags    // 一般置 0。

);

不论是客户端还是服务端的应用程序都用 send() 函数向 TCP 连接的另一端发送数据。

客户端一般用 send() 函数 向服务器发送请求,而服务器通常用 send() 函数来向客户端程序发送应答。

对于同步 Socket 的 send() 函数执行流程,当调用它时,send 先比较待发送数据的长度(len)和套接字s 的发送端缓冲区大小。

如果 len 大于 s 的发送缓冲区的长度,该函数就返回 SOCKET_ERROR,发送失败。

反之,那么 send 先检查协议是否正在发送 s 发送缓冲区的数据。如果是,就等待协议把数据发送完,

如果协议还没有开始发送 s 的发送缓冲区的数据 或者 s 的发送缓冲区中没有数据,

那么send 就比较 s  的发送缓冲区的剩余空间和 len 的大小。如果 len 大于剩余空间大小,

send 就一直等待协议把 s 的发送缓冲区中的数据发送完,反之,send 就仅仅把 buf 中的数据复制到剩余空间里

注意并不是 send 把 s 的发送缓冲区中的数据传到连接的另一端的,而是协议传的,

send 仅仅是把 buf 中的数据复制到 s 的发送缓冲区的剩余空间里)。

如果 send() 函数复制数据成功,就返回实际复制的字节数,否则,就返回 SOCKET_ERROR。

如果 send() 函数在等待协议传送数据时网络断开,也返回 SOCKET_ERROR。

send() 函数把 buf 中的数据成功复制到 s 的发送缓冲区的剩余空间中后它就返回了,但是此时这些数据

并不一定马上就传到连接的另一端。

如果协议在后续的传递过程中出现网络错误的话,那么下一个 socket 函数就会返回 SOCKET_ERROER。

提示:

每一个除 send 外的 socket 函数在执行最开始总要等待套接字的发送缓冲区中的数据被协议传送完毕才能继续,

如果出现网络错误,那么该 socket 函数就返回 SOCKET_ERROR。

recv() 函数原型:

int recv(

    SOCKET s,      // 指定接收端套接字描述符。

    char FAR *buf,  // 指明一个缓冲区,该缓冲区用来存放 recv() 函数接收到的数据。

    int len,     // 指明 buf 的长度。

    int flags   // 一般置 0。

);

不论客户端还是服务器端应用程序都用 recv() 函数从 TCP/IP 连接的另一端接收数据。

对于同步 Socket 的 recv() 函数执行流程,当调用它时,recv() 函数先等待 s 的发送缓冲区中的数据传输完毕。

如果协议在传送 s 的发送缓冲区中的数据时出现网络错误的话,那么 recv() 函数就会返回 SOCKET_ERROER。

如果 s 的发送缓冲区中没有数据 或者数据被协议接收完毕后,recv() 函数 会先检查套接字 s 的接收缓冲区,

如果 s 的接收缓冲区中没有数据或协议正在接收数据,那么 recv() 函数就会一直等待,直到数据接收完毕。

当协议把数据接收完毕,recv() 函数就把 s 的接收缓冲区中的数据拷贝到 buf 中。

(注意协议接收到的数据可能大于 buf 的长度,所以在这种情况下需要调用几次 recv() 函数才能把 s

接收缓冲区的数据拷贝完。recv() 函数仅仅是拷贝数据,真正的接收数据是协议完成的。)

recv() 函数返回其实是拷贝的字节数,如果 recv() 函数在拷贝时出错,那么它返回 SOCKET_ERROR。

如果 recv() 函数在等待协议接收数据时网络中断,那么它返回 0。

sendto() 函数原型:

int sendto(

    SOCKET s,         // 指定发送端套接字描述符。

    const char *buf,  // 指明一个存放应用程序要发送数据的缓冲区。

    int len,     // 指明实际要发送的数据字节数。

    int flags,   // 一般置 0。

    const struct sockaddr* to,  // 为指向目的地址的指针。(表示目的机的 ip 和 port).

    int tolen    // 为 to 的长度。(一般赋值为 sizeof(sturct sockaddr).

);

recvfrom() 函数原型:

int recvfrom(

    SOCKET s,   // 指定接收端的套接字描述符。

    char *buf,  // 指明一个缓冲区,该缓冲区用来存放 recvfrom() 函数接收到的数据。

    int len,    // 指明 buf 的长度。

    int flags,  // 一般置 0.

    struct sockaddr *from,  // 为数据包的来源地址。

    int *fromlen   // 数据包的长度。

);
#include<stdio.h>
#include<winsock.h>
#pragma comment(lib,"ws2_32")
#define PORT 1234
int main(void)
{
SOCKET sockfd;
WSADATA ws;
char Buffer[MAX_PATH];
struct sockaddr_in their_addr; if(WSAStartup(MAKEWORD(, ), &ws) != 0)
{
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
exit(0);
} their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if (connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
closesocket(sockfd);
exit(0);
}
printf("input your msg:\n");
gets_s(Buffer);
send(sockfd, Buffer, MAX_PATH, );
closesocket(sockfd);
WSACleanup();
getchar();
return ;
}

客户端 SOCKET 编程的更多相关文章

  1. socket编程学习step1

    socket学习参考链接,赞一个:http://blog.csdn.net/hguisu/article/details/7445768 sockets(套接字)编程有三种,流式套接字(SOCK_ST ...

  2. socket编程中客户端常用函数

    1 常用函数 1.1   connect() int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen); 客 ...

  3. Windows Socket 编程_单个服务器对多个客户端简单通讯

    单个服务器对多个客户端程序: 一.简要说明 二.查看效果 三.编写思路 四.程序源代码 五.存在问题 一.简要说明: 程序名为:TcpSocketOneServerToMulClient 程序功能:实 ...

  4. 你得学会并且学得会的Socket编程基础知识(续)——Silverlight客户端

    本文将在这个案例的基础上,加入一个特殊场景,利用Silverlight来实现客户端.有的朋友可能会说,其实是一样的吧.请不要急于下结论,有用过Silverlight的朋友都有这种体会,很多在标准.NE ...

  5. Python Socket 网络编程 (客户端的编程)

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  6. 利用socket编程在ESP32上搭建一个TCP客户端

    通过之前http://www.cnblogs.com/noticeable/p/7636582.html中对socket的编程,已经可以知道如何通过socket编程搭建服务器和客户端了,现在,就在ES ...

  7. socket编程:客户端与服务器间的连接以及各函数的用法

    在认真的看UNP之前,一直被socket编程说的云里雾里,今天我要让大家从整天上认识socket编程,让我们知道socket编程的整个流程和各个函数的用法.这样:我们在写一些简单的socket编程时就 ...

  8. java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求

    1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...

  9. java socket编程(li)

    一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以 ...

随机推荐

  1. [币严区块链]USDT钱包节点搭建

    USDT是基于BTC发的稳定币,它是比特币的一条侧链,说简单点,就是在比特币区块数据的不可篡改性与区块唯一性的基础上,再封装了一层.具体原理可网上查资料.总之理解一点:USDT的钱包节点就是BTC的钱 ...

  2. Python连载38-协程、可迭代、迭代器、生产者消费者模型

    一.生产者消费者模型 import multiprocessing from time import ctime def consumer(input_q): print("Into con ...

  3. ExpandableListView之BaseExpandableListAdapter

    之前使用的SimpleExpandableListAdapter有较大局限性,样式单一,修改难度大,这里不建议使用,而是利用BaseExpandableListAdapter,其实SimpleExpa ...

  4. js vue 页面添加水印

    vue 微信页面添加水印 this.$nextTick(function() {                                   watermark({ watermark_txt ...

  5. Django+MySQL Dashboard 网页端数据库可视化

    1. Overview Python+MySQL+Django, 有些数据托管在 MySQL 的数据库,然后我们希望进行可视化,通过 web 的方式对数据库的信息去进行展示/检索/维护/.. 这个项目 ...

  6. JSP常规内容

    1.forword和redirect的区别? forword是服务器请求资源,服务器直接读取URL,把目标地址URL响应读取出来,然后再把这些内容发送给浏览器.(特点是url和request sess ...

  7. TCP/IP 物理层卷一 -- 基本概念

    一.基本概念: 物理层:TCP/IP 协议簇的最底层,物理层所需要考虑的是如何在连接计算机的传输媒体上传输数据的比特流,而不是连接计算机的具体物理设备. 信号:数据的电气或电磁表现,是数据在传输媒体上 ...

  8. 用Python帮你实现IP子网计算

    目录 0. 前言 1. ipaddress模块介绍 1.1 IP主机地址 1.2 定义网络 1.3 主机接口 1.4 检查address/network/interface对象 1.4.1 检查IP版 ...

  9. abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理二 (二十)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  10. 要不要学习Git(分布式版本控制系统)

    做技术的人,要不要学一学Git呢? 提出这个问题,是因为很多小伙伴还不会使用Git. 对于任何新一代的技术工具,它在业界普及都有一个过程,Git的阻碍是:学习成本.工具迭代的成本. SVN诞生于200 ...