winsock入门之建立socket
来源:互联网 发布:淘宝号申请注册 编辑:程序博客网 时间:2024/06/08 11:25
不只是winsock,几乎所有网络程序可以分为5个步骤:
1. 打开socket
2. 命名socket
3. 与另一个socket建立关联
4. 与socket之间发送和接收数据
5. 关闭socket
(一)下面主要说明连接的建立过程。
打开socket:int socket(intaf, int type, int protocol);
参数说明:
af: 地址族的类型AF_UNIXAF_INET
type: 数据格式:流SOCK_STREAM/报文SOCK_DGRAM
protocol: 协议类型
命名socket:intbind(SOCKET s, struct sockaddr FAR *addr, int namelen);
参数说明:
s:socket句柄。
addr:指向socket地址结构的指针。
namelen:addr所指向的socket结构的长度。
这里用到的一个数据结构sockaddr_in是给socket命名的关键,具体如下:
struct sockaddr_in{
short sin_family;//地址族
u_short sin_port;//端口号
struct in_addr sin_addr;//地址
char sin_zero[8];//没用
};//这里当然都是绑定本机地址127.0.0.1
第1、2步是服务器和客户端都要做的,但是一般情况下客户端为了防止端口号冲突会采用隐式命名的方式,在向服务器发起连接的时候(调用connect()函数)协议栈会分配给客户端独有的端口号。
3.1.服务器监听客户端
int PASCAL FAR listen(SOCKETs, int backlog);
3.2.客户端发起连接
int PASCAL FAR connet(SOCKETs, struct sokaddr FAR *addr, int namelen);
3.3.服务器完成连接
从监听socket上接受一个等待的连接请求后,accept()函数为新创建的连接返回一个新的socket。
SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR *addr, int FAR*addrlen);
(二)接下来就是发送数据和关闭套接字了。
这里我实现了两个功能:发送消息和发送文件。
客户端首先选择发送类型:1.消息;2.文件
两种方式实现起来没有大差别,只是在发送文件的时候首先发送一个标志FILE_FLAG " xmzulesile "提醒服务器将要发送文件,然后服务器将接收到的字节流写入文件,客户端发送文件结束后发送一个标志FILE_SEND_OVER "over",服务器收到后知道发送结束给客户端发送”Received!”。
最后说明一个问题:这里可以说使用了停-等协议,发送一个数据包收到确认再发送下一个数据包,否则客户端连续发送完所有数据包(包括结束标志),服务器收不到结束标志,就会一直阻塞下去。具体原因还没想明白,一开始没有加"接收确认"的时候,调试是没问题的,但是运行就会阻塞。
上面就是工作流程,结束后就可以关闭套接字了。
附上源代码:
客户端:
#include <stdio.h>#include <winsock2.h>#include <tchar.h>#pragma comment(lib, "ws2_32.lib") //加载库文件char FILE_FLAG[12] = "xmzulesile"; // 发送文件的标志char FILE_SEND_OVER[10] = "over"; // 发送文件结束的标志int main(){// 初始化WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != NO_ERROR){printf_s("failed to initialize!\n");return 0;}// 建立socketSOCKET m_socketServer;// 连接服务器的套接字m_socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (m_socketServer == INVALID_SOCKET){printf_s("failed to create client socket!\n");WSACleanup();return 0;}sockaddr_in clientAddr;clientAddr.sin_family = AF_INET;clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");clientAddr.sin_port = htons(3579);// 连接到服务器if (connect(m_socketServer, (SOCKADDR*)&clientAddr, sizeof(clientAddr)) == SOCKET_ERROR){printf_s("failed to connect\n");closesocket(m_socketServer);WSACleanup();return 0;}char c;char buf[1024 + 1] = { 0 };char filename[255];FILE *fp = NULL;//send(m_socketServer, buf, strlen(buf), 0);// 发送数据while (TRUE){printf_s("发送:1.消息;2.文件\n");if ((c = getchar()) == '1'){getchar();// 丢弃回车符gets_s(buf, 1024);// 读取消息send(m_socketServer, buf, strlen(buf), 0);}else if (c == '2'){getchar();// 丢弃回车符printf_s("请输入本地文件路径: ");scanf_s("%s",&filename, 255);getchar();// 丢弃回车符if (fopen_s(&fp, filename, "rb+")){::MessageBox(NULL, _T("failed to open file in client"), NULL, 0);return 0;}send(m_socketServer, FILE_FLAG, sizeof(FILE_FLAG), 0);//通知服务器将要发送文件// 读取文件int i = fread(buf, 1, 1024, fp);while (i > 0){//这里可以说使用停-等协议,发送一个数据包收到确认再发送下一个数据包//否则客户端连续发送完所有数据包(包括结束标志),服务器收不到结束标志,就会一直阻塞下去//具体原因还没想明白,一开始没有加"接收确认"的时候,调试是没问题的,但是运行就会阻塞send(m_socketServer, buf, i, 0);recv(m_socketServer, buf, 1024, 0);//接收确认SecureZeroMemory(buf, sizeof(buf));i = fread(buf, 1, 1024, fp);}if (ferror(fp)){MessageBox(NULL, _T("fread error"), NULL, 0);return 0;}//告诉服务器发送完毕send(m_socketServer, FILE_SEND_OVER, sizeof(FILE_SEND_OVER), 0);//接收通知(服务器接收完毕)int ret = recv(m_socketServer, buf, 1024, 0);if (ret == 0){printf("Recv data error: %d\n", WSAGetLastError());return 0;}if (buf[0])//输出服务器发过来的消息{buf[ret] = 0;printf_s("Server:%s\n", buf);}if (fp){fclose(fp);//关闭文件fp = NULL;}}else{getchar();printf_s("incorrect input\n");}}closesocket(m_socketServer);WSACleanup();return 0;}
#include <WinSock2.h>#include <iostream>#include <string.h>#include <tchar.h>#pragma comment(lib, "ws2_32.lib")char FILE_FLAG[12] = "xmzulesile"; // 客户端发来文件的标志char FILE_SEND_OVER[10] = "over"; // 客户端发送文件结束的标志//接收文件unsigned recvFile(SOCKET s, const char *filename){FILE *fp;char buf[1024] = { 0 };int ret = 0;if (fopen_s(&fp, filename, "wb+")){::MessageBox(NULL, _T("failed to write file in server"), NULL, 0);return 0;}do{//接收数据ret = recv(s, buf, 1024, 0);if (ret == 0){printf("Recv data error: %d\n", WSAGetLastError());return 0;}//是否接收结束if (!strcmp(buf, FILE_SEND_OVER)){send(s, "Received!", 10, 0);//通知发送端全部接收完毕break;}else{//把数据写入打开的文件fwrite(buf, 1, ret, fp);send(s, "Got it", 10, 0);//发送确认SecureZeroMemory(buf, sizeof(buf));}} while (ret > 0);if (fp){fclose(fp);fp = NULL;}return 0;}int main(){WSADATA wsaData;int iInit = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iInit != NO_ERROR){printf_s("failed to initialize!\n");return 0;}SOCKET m_socketListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (m_socketListen == INVALID_SOCKET){printf_s("failed to create server socket!\n");WSACleanup();return 0;}sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");serverAddr.sin_port = htons(3579);//bindif (bind(m_socketListen, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR){printf_s("failed to bind!\n");closesocket(m_socketListen);WSACleanup();return 0;}//listenif (listen(m_socketListen, 1) == SOCKET_ERROR) {printf_s("listen failed\n");closesocket(m_socketListen);WSACleanup();return 0;}//accept//从监听socket上接受一个等待的连接请求后,accept()函数为新创建的连接返回一个新的socketSOCKET m_socketClient = accept(m_socketListen, NULL, NULL);// 跟客户端连接的套接字if (m_socketClient == INVALID_SOCKET) {wprintf(L"accept failed with error: %ld\n", WSAGetLastError());closesocket(m_socketListen);WSACleanup();return 0;}int bytes = SOCKET_ERROR;char buf[1024] = { 0 };//接收数据while (TRUE){if((bytes = recv(m_socketClient, buf, 1024, 0)) == 0){break;}if (!strcmp(FILE_FLAG, buf)){printf_s("Here comes a file\n");recvFile(m_socketClient, "d:\\recv");}else{buf[bytes] = '\0';// 字符串结尾标志printf_s("Client:%s\n", buf);}}closesocket(m_socketListen);WSACleanup();return 0;}
- winsock入门之建立socket
- winsock编程,socket建立步骤
- Winsock使用之创建客户端Socket
- Windows Socket套接字(二)-MSDN:winsock入门
- WinSock入门
- winsock编程宝典之TCP连接建立与关闭
- Winsock 网络编程 Socket模型之Select模型
- Winsock 网络编程 Socket模型之WSAAsyncSelect模型
- Winsock 网络编程 Socket模型之WSAEventSelect模型
- Winsock 网络编程 Socket模型之Overlapped模型
- Winsock 网络编程 Socket模型之Completion模型
- Python 之 socket 入门
- winsock.h(Socket编程)
- Winsock API:socket
- STM32入门之模板建立
- 非阻塞模式WinSock编程入门(Socket关联窗口消息机制)
- Winsock学习 --- 建立套接字
- 网络爬虫之建立socket链接
- linux 动态库路径查找
- C/C++ 初学简单笔记 —2.1— 类的友元
- Linux文件锁flock
- 开发者需知的10类工具
- c++builder 2010 with OpenSSL
- winsock入门之建立socket
- 用Node.js实现Restful风格webservice
- (转载优质文)定制iOS 7中的导航栏和状态栏
- 【iOS7的一些总结】3、视图控制器ViewControllers之间的数据传递(2)
- Iterable接口
- 1_04感想
- 人品问题
- 妹子尚且如此! 少年努力吧
- EL 表达式学习中的 几个注意点。