PPC的C/C++和人工智能学习笔记
每一篇学习笔记,都只是为了更好地掌握和理解

C语言基础(20)_socket编程(1)

首次学习socket网络编程,今天只是尝试建立一个能够通过网络互相通信的两个简单程序。

 

现在尝试在windows平台的vs2015上写出简单的网络通信程序:

 

一:头文件:

#define WIN32_LEAN_AND_MEAN

//这个可以解决 winsock2.h 写在 windows.h下面的错误,MSDN上这么写的

#define _WINSOCK_DEPRECATED_NO_WARNINGS //解决inet_addr(“127.0.0.1″)的警告

#include <winsock2.h>

#include <windows.h>

#pragma comment(lib,”ws2_32.lib”) //调用lib

 

二:版本协商(windows专有)(MSDN上copy下来的)

WORD wVersionRequested;

WSADATA wsaData;

int err;

 

/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */

wVersionRequested = MAKEWORD(2, 2);

 

err = WSAStartup(wVersionRequested, &wsaData);

if (err != 0) {

/* Tell the user that we could not find a usable */

/* Winsock DLL.                                  */

printf(“WSAStartup failed with error: %d\n”, err);

return 1;

}

 

/* Confirm that the WinSock DLL supports 2.2.*/

/* Note that if the DLL supports versions greater    */

/* than 2.2 in addition to 2.2, it will still return */

/* 2.2 in wVersion since that is the version we      */

/* requested.                                        */

 

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {

/* Tell the user that we could not find a usable */

/* WinSock DLL.                                  */

printf(“Could not find a usable version of Winsock.dll\n”);

WSACleanup();

return 1;

}

else

printf(“The Winsock 2.2 dll was found okay\n”);

 

【这里写正常的代码】

在最后,加上:WSACleanup();

服务器端流程:

①创建套接字(socket)

②服务绑定(bind)

③服务侦听(listen)

④处理新到连接(accept)

⑤数据收发(recv\send)

⑥套接字关闭(close)

客户端流程:

①客户端套接字创建(socket)

②发起连接 (connect)

③数据发收(send\recv)

④套接字关闭(close)

 

创建套接字Socket:

SOCKET PASCAL FAR socket ( _In_ int af,  _In_ int type, _In_ int protocol);

参数:af表示所使用的协议家族,一般写AF_INET(代表的是IP家族)。/* internetwork: UDP, TCP, etc. */

type表示socket的类型,SOCK_STREAM(TCP)或SOCK_DGRAM(UDP),Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;

protocol通常写0;

 

绑定套接字:

int WSAAPI bind(_In_ SOCKET s,

_In_reads_bytes_(namelen) const struct sockaddr FAR * name,

_In_ int namelen );

如:bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));

 

服务侦听

如:listen(sockServer, 5); //后面参数是 监听队列大小

 

处理新到连接:

如:sockConn = accept(sockServer, (SOCKADDR*)&addrClient, &len);

 

发起连接:

如:int res = connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));

 

发送数据:

如:send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);

 

接收数据:

如:recv(sockConn, recvBuf, 256, 0);

 

套接字关闭:

如:closesocket(sockClient);

 

基于TCP的最简单类似对讲机模式的聊天程序代码:

//tcp_server_对讲机.cpp
//TCP Server 对讲机模式
#define WIN32_LEAN_AND_MEAN //这个可以解决 winsock2.h 写在 windows.h下面的错误,MSDN上copy
#define _WINSOCK_DEPRECATED_NO_WARNINGS //解决inet_addr("ip")的警告
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")

int main() {
 //一、版本协商
 WORD wVersionRequested; //WORD == unsigned short
 WSADATA wsaData;
 wVersionRequested = MAKEWORD(2, 2);
 int err = WSAStartup(wVersionRequested, &wsaData);
 if (err != 0) {
 printf("WSAStartup Error!\n");
 return -1;
 }
 if (LOBYTE(wVersionRequested) != 2 || HIBYTE(wVersionRequested) != 2) {
 printf("对应版本的Winsock.dll没有找到。\n");
 WSACleanup();
 return -1;
 }
 else
 printf("Winsock 2.2 DLL OK!\n");

 //二、创建套接字
 SOCKET sockSer;
 sockSer = socket(AF_INET, SOCK_STREAM, 0);

 //三、绑定套接字
 SOCKADDR_IN addrSer; //服务端的地址信息
 addrSer.sin_family = AF_INET;
 addrSer.sin_port = htons(5050);
 addrSer.sin_addr.S_un.S_addr = INADDR_ANY; //或者inet_addr("127.0.0.1");
 bind(sockSer, (SOCKADDR*)&addrSer, sizeof(SOCKADDR));

 //四、侦听
 listen(sockSer, 5);// 5表示 侦听队列的大小

 //五、准备接受客户端连接
 SOCKET sockConn; //连接的套接字
 SOCKADDR_IN addrCli; //客户端的地址信息
 int len = sizeof(SOCKADDR); 
 printf("等待客户端连接...\n");
 sockConn = accept(sockSer, (SOCKADDR*)&addrCli, &len); //这里的长度是个指针
 char *cliIP = NULL;
 if (sockConn == INVALID_SOCKET) { //判断连接是否成功
 printf("服务端接收客户端连接失败!\n");
 return -1;
 }
 else {
 cliIP = inet_ntoa(addrCli.sin_addr);
 //printf("服务端接收客户端%u.%u.%u.%u连接成功!\n", 
 // addrCli.sin_addr.S_un.S_un_b.s_b1,addrCli.sin_addr.S_un.S_un_b.s_b2, 
 // addrCli.sin_addr.S_un.S_un_b.s_b3,addrCli.sin_addr.S_un.S_un_b.s_b4);
 printf("服务端接收客户端%s连接成功!\n", cliIP);
 }

 //六、接收和发送数据
 char sendbuf[256]; //发送缓冲区
 char recvbuf[256]; //接收缓冲区
 sprintf(sendbuf, "欢迎你,%s", cliIP);
 printf("输入quit退出!\n");
 printf("服务端:>%s\n", sendbuf); //发送给客户端
 send(sockConn, sendbuf, strlen(sendbuf) + 1, 0);
 while (1) {
 printf("客户端:>");
 recv(sockConn, recvbuf, 256, 0);
 printf("%s\n",recvbuf);
 printf("服务端:>");
 gets_s(sendbuf,255);
 if (strcmp(sendbuf, "quit") == 0) break;
 send(sockConn, sendbuf, strlen(sendbuf) + 1, 0);
 }

 //七、关闭套接字
 closesocket(sockSer);
 WSACleanup();

 return 0;
}

//tcp_client_对讲机.cpp
//TCP Client 对讲机模式
#define WIN32_LEAN_AND_MEAN //这个可以解决 winsock2.h 写在 windows.h下面的错误,MSDN上copy
#define _WINSOCK_DEPRECATED_NO_WARNINGS //解决inet_addr("ip")的警告
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")

int main() {
 //一、版本协商
 WORD wVersionRequested; //WORD == unsigned short
 WSADATA wsaData;
 wVersionRequested = MAKEWORD(2, 2);
 int err = WSAStartup(wVersionRequested, &wsaData);
 if (err != 0) {
 printf("WSAStartup Error!\n");
 return -1;
 }
 if (LOBYTE(wVersionRequested) != 2 || HIBYTE(wVersionRequested) != 2) {
 printf("对应版本的Winsock.dll没有找到。\n");
 WSACleanup();
 return -1;
 }
 else
 printf("Winsock 2.2 DLL OK!\n");

 //二、创建套接字
 SOCKET sockCli;
 sockCli = socket(AF_INET, SOCK_STREAM, 0);

 //三、连接服务器
 SOCKADDR_IN addrSer;
 addrSer.sin_family = AF_INET;
 addrSer.sin_port = htons(5050);
 addrSer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 int res = connect(sockCli, (SOCKADDR*)&addrSer, sizeof(SOCKADDR));
 if (res != 0) {
 printf("连接服务器失败!\n");
 return -1;
 }
 printf("连接服务器成功!\n");

 //四、接收和发送数据
 char sendbuf[256];
 char recvbuf[256];
 printf("输入quit退出!\n");
 while (1) {
 printf("服务端:>");
 recv(sockCli, recvbuf, 255, 0);
 printf("%s\n", recvbuf);
 printf("客户端:>");
 gets_s(sendbuf, 255);
 if (strcmp(sendbuf, "quit") == 0) break;
 send(sockCli, sendbuf, strlen(sendbuf) + 1, 0);
 }
 
 //五、关闭套接字
 closesocket(sockCli);
 WSACleanup();
 return 0;
}

(2017-03-20 www.vsppc.com)

学习笔记未经允许不得转载:PPC的C/C++和人工智能学习笔记 » C语言基础(20)_socket编程(1)

分享到:更多 ()

评论 74

评论前必须登录!