建立客户端的 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. React Hooks 你不来了解下?

    前言 最近在看 React 的新语法-- React Hooks,只能一句话概括:React 语法真的是越来越强大,越写代码越少. 强烈推荐还没看 React Hooks 的同学去学习下,这会让你写r ...

  2. xml文档的解析并通过工具类实现java实体类的映射:XML工具-XmlUtil

    若有疑问,可以联系我本人微信:Y1141100952 声明:本文章为原稿,转载必须说明 本文章地址,否则一旦发现,必追究法律责任 1:本文章显示通过 XML工具-XmlUtil工具实现解析soap报文 ...

  3. C++输入输出常用格式(cin,cout,stringstream)

    输入格式 1.cin>>a; 最基本的格式,适用于各种类型.会过滤掉不可见字符例如空格,TAB,回车等 2.cin>>noskipws>>ch[i]; 使用了 no ...

  4. 装系统---------- u盘 安装系统

    1.首先根据你的电脑品牌进入bios 模式 如何进入:  不同电脑品牌进入bios 方法 进入之后设置启动方式 将第一启动设置为U盘启动设置好后 使用 Fn + F10  保存 2.使用制作好的 U盘 ...

  5. 02 (H5*) Vue第二天

    目录: 1:全局过滤器的使用 2:局部过滤器 3:自定义键盘码 4:自定义指令 5:自定义私有指令 6:Vue生命周期. 7:网络请求 1:全局过滤器的使用 Vue.filter("msgF ...

  6. 03: OpenGL ES 基础教程02 使用OpenGL ES 基本步骤

    第二章:让硬件为你工作(OpenGL ES 应用实践指南 iOS卷) 前言: 1:使用OpenGL ES 基本步骤 2:绘制三角形 3:效果 正文: 一:使用OpenGL ES 基本步骤 1:生成缓存 ...

  7. Nginx限流

    文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 在当今流量徒增的互联网时代,很多业务场景都会涉及到高并发.这个时候接口进行限流是非常有必要的,而限流是Ngin ...

  8. 标准io和管道练习

         标准IO和管道实验练习 [例1]把/etc/fstab文件内容重定向到/tmp目录下文件名为fstab.out 写法: 13:54:35 root@centos ~]#cat /etc/fs ...

  9. 自定义构建基于.net core 的基础镜像

    先说一个问题 首先记录一个问题,今天在用 Jenkins 构建项目的时候突然出现包源的错误: /usr/share/dotnet/sdk/2.2.104/NuGet.targets(114,5): e ...

  10. ajax跨域访问数据

    通过json发送和接受数据,数据以json的格式在服务器端和前台进行传递,什么是json数据?这里就不进行详细阐述,轻自行百度解决. 在html5 中利用ajax 异步请求时,会遇到跨域的问题,如果域 ...