基于TCP(面向连接)的socket编程,分为客户端和服务器端。
客户端的流程如下:
(1)创建套接字(socket)
(2)向服务器发出连接请求(connect)
(3)和服务器端进行通信(send/recv)
(4)关闭套接字
服务器端的流程如下:
(1)创建套接字(socket)
(2)将套接字绑定到一个本地地址和端口上(bind)
(3)将套接字设为监听模式,准备接收客户端请求(listen)
(4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
(5)用返回的套接字和客户端进行通信(send/recv)
(6)返回,等待另一个客户请求。
(7)关闭套接字。
下面通过一个具体例子讲解一下具体的过程和相关的函数。
客户端代码,运行于vs2008
[cpp] view plaincopy
// ClientTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int ret;
SOCKET sClient; //连接套接字
struct sockaddr_in saServer; //服务器地址信息
char *ptr;
BOOL fSuccess = TRUE;
//WinSock初始化
wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本
ret = WSAStartup(wVersionRequested, &wsaData); //加载套接字库
if(ret!=0)
{
printf("WSAStartup() failed!\n");
//return 0;
}
//确认WinSock DLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup(); //释放为该程序分配的资源,终止对winsock动态库的使用
printf("Invalid WinSock version!\n");
//return 0;
}
//创建Socket,使用TCP协议
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
WSACleanup();
printf("socket() failed!\n");
//return 0;
}
//构建服务器地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//连接服务器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("connect() failed!\n");
closesocket(sClient); //关闭套接字
WSACleanup();
//return 0;
}
char sendMessage[]="ZhongXingPengYue";
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed!\n");
}
else
printf("client info has been sent!");
char recvBuf[100];
recv(sClient,recvBuf,100,0);
printf("%s\n",recvBuf);
closesocket(sClient); //关闭套接字
WSACleanup();
getchar();
//return 0;
}
<span style="font-size:16px;"></span>
[cpp] view plaincopy
<span style="font-size:16px;"></span>
第一步,加载套接字。使用WSAStartup 函数,如:ret = WSAStartup(wVersionRequested, &wsaData)。WSAStartup函数的原型为
[cpp] view plaincopy
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
第一参数wVersionRequested,用来指定准备加载的winsock库的版本。利用MAKEWORD(x,y)宏来赋值。x是高位字节,表示副版本号;y是低位字节,表示主版本号。MAKEWORD(2, 2)表示版本号为2.2。
第二个参数是指向WSADATA结构的指针,是一个返回值,保存了库版本的有关信息。
第二步,创建套接字。使用socket函数,如:sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)。socket函数的原型为:
[cpp] view plaincopy
SOCKET socket(int af, int type, int protocol );
第一个参数,指定地址族,对于TCP/IP协议的套接字,只能为AF_INET;
第二个参数,指定socket类型,SOCK_STREAM指产生流式套接字,SOCK_DGRAM指产生数据报套接字,TCP/IP协议使用SOCK_STREAM。
第三个参数,与特定的地址家族相关的协议,TCP协议一般为IPPROTO_TCP。也可以写0,那么系统会根据地址格式和套接字类别,自动选择一个适合的协议。
如果socket创建成功,则返回一个新的SOCKET数据类型的套接字描述符;若失败,则返回INVALID_SOCKET,由此可以判断是否创建成功。
第三步,连接服务器。使用connect函数,如:ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer))。connect函数函数原型为
[csharp] view plaincopy
int connect(SOCKET s, const struct sockaddr FAR* name, int namelen);
第一个参数是将在上面建立连接的那个套接字的描述符,即之前创建socket的返回值sClient。
第二个参数是要连接的服务器端的地址信息。它是一个结构体类型struct sockaddr_in ,需要在调用connect函数之前构建服务器地址信息。sockaddr_in的定义如下:
[cpp] view plaincopy
struct sockaddr_in{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8]
};
设置服务器端口时,用到htons函数,该函数把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序,因为不同的计算机存放多字节的顺序不同(基于Intel CPU是高字节存放在低地址,低字节存放在高地址),所以网络中不同主机间通信时,要统一采用网络字节顺序。设置服务器IP地址时,使用到inet_addr函数,它是将点分十进制的IP地址的字符串转换成unsigned long型。inet_ntoa函数做相反的转换。
第三个参数是服务器端地址结构体的大小。
第四步,发送。使用send函数向服务器发送数据,如:ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0)。send函数的原型为
[cpp] view plaincopy
int send(SOCKET s, const char FAR* buf, int len, int flags);
第一个参数,是一个与服务器已经建立连接的套接字。
第二个参数,指向包含要发送的数据的缓冲区的指针。
第三个参数,是所指向的缓冲区的长度。准确的说,应该是所要发送的数据的长度,因为不是缓冲区的所有数据都要同时发送。
第四个参数,它设定的值将影响函数的行为,一般将其设置为0即可。
如果发送失败,send会返回SOCKET_ERROR,由此可以判断发送是否成功。
第五步,接收。使用recv函数接收服务器发过来的数据,如recv(sClient,recvBuf,100,0)。recv函数的原型为
[cpp] view plaincopy
int recv(SOCKET s, const char FAR* buf, int len, int flags);
recv函数的参数的含义和send函数参数含义差不多,只是第二个参数是指向用来保存接收数据的缓冲区的指针。recv函数的返回值应该是所接收的数据的长度,如果返回SOCKET_ERROR表示接收失败;返回0表示服务器端关闭连接。
第六步,关闭socket,释放资源。使用closesocket函数关闭套接字,如closesocket(sClient);使用WSACleanup函数释放为该程序分配的资源,终止对winsock动态库的使用,如WSACleanup();
服务器端代码,运行于vs2008
[cpp] view plaincopy
// ServerTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int ret, nLeft, length;
SOCKET sListen, sServer; //侦听套接字,连接套接字
struct sockaddr_in saServer, saClient; //地址信息
char *ptr;//用于遍历信息的指针
//WinSock初始化
wVersionRequested=MAKEWORD(2, 2); //希望使用的WinSock DLL 的版本
ret=WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf("WSAStartup() failed!\n");
//return 0;
}
//创建Socket,使用TCP协议
sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
WSACleanup();
printf("socket() faild!\n");
//return 0;
}
//构建本地地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意转化为网络字节序
saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用INADDR_ANY 指示任意地址
//绑定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("bind() faild! code:%d\n", WSAGetLastError());
closesocket(sListen); //关闭套接字
WSACleanup();
//return 0;
}
//侦听连接请求
ret = listen(sListen, 5);
没有合适的资源?快使用搜索试试~ 我知道了~
VC6.0实现socket、tcp传输,支持各类文件
共34个文件
pdb:4个
db:3个
idb:2个
3星 · 超过75%的资源 需积分: 50 196 下载量 154 浏览量
2015-05-21
20:01:01
上传
评论 16
收藏 12.07MB ZIP 举报
温馨提示
VC6.0实现socket、tcp传输,支持各类文件,本人测试成功的 图片,普通txt文件,其他未测试,但相信可行,代码简单明了
资源推荐
资源详情
资源评论
收起资源包目录
file_transfer.zip (34个子文件)
file_transfer
file_transfer_server
file_transfer_server.cpp 2KB
file_transfer_server.ncb 41KB
file_transfer_server.dsw 546B
Debug
vc60.pdb 76KB
file_transfer_server.obj 15KB
file_transfer_server.pdb 465KB
vc60.idb 145KB
file_transfer_server.exe 168KB
file_transfer_server.ilk 197KB
file_transfer_server.pch 3.39MB
Thumbs.db 19KB
file_transfer_server.dsp 4KB
file_transfer_server.plg 1KB
file_transfer_server.opt 48KB
Thumbs.db 35KB
file_transfer_client
11.jpg 3KB
file_transfer_client.dsw 546B
file_transfer_client.opt 48KB
11.bmp 14KB
11.ts 9.82MB
11.png 3KB
Debug
file_transfer_client.pdb 513KB
vc60.pdb 76KB
file_transfer_client.pch 3.47MB
file_transfer_client.ilk 232KB
vc60.idb 153KB
file_transfer_client.obj 16KB
file_transfer_client.exe 176KB
file_transfer_client.ncb 41KB
file_transfer_client.cpp 2KB
file_transfer_client.plg 1KB
11.txt 12KB
file_transfer_client.dsp 4KB
Thumbs.db 102KB
共 34 条
- 1
资源评论
- thumbsup2020-03-27可以参考一下
- (*^_^*)小原2018-05-01用着还可以
黄忻
- 粉丝: 27
- 资源: 108
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功