Socket编程--基础(基本server/client实现)

  • IPv4套接口地址结构

    •   IPv4套接口地址结构通常也称为“网际套接字地址结构”,它以“sockaddr_in”命名,定义在头文件中
    •   LINUX结构下的常用结构,一般创建套接字的时候都要将这个结构里面的值进行初始化
    • struct sockaddr_in
      {
          sa_family_t    sin_family; /* address family: AF_INET */
          in_port_t      sin_port;   /* port in network byte order(网络字节序) */
          struct in_addr sin_addr;   /* internet address */
      };
      /* Internet address. */
      struct in_addr
      {
          uint32_t       s_addr;     /* address in network byte order */
      };  
  • socket函数 
    • #include <sys/types.h>
      #include <sys/socket.h>
      int socket(int domain, int type, int protocol);  
      
      //创建一个套接字用于通信   参数分析domain:指定通信协议族(protocol family),常用取值AF_INET(IPv4)type:指定socket类型, 流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAWprotocol:协议类型,常用取值0, 使用默认协议返回值:成功: 返回非负整数,套接字;失败: 返回-1
  • bind函数
    • int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);  //addrlen--地址长度
      绑定一个本地地址到套接字。绑定函数
      参数:
      sockfd:socket函数返回的套接字
      addr:要绑定的地址
  • listen函数
    • int listen(int sockfd, int backlog);  listen函数应该用在调用socket和bind函数之后, 并且用在调用accept之前, 用于将一个套接字从一个主动套接字转变成为被动套接字。使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。
      
         sockfd 一个已绑定未被连接的套接字描述符   backlog说明:对于给定的监听套接口,内核要维护两个队列:1、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程(SYN_RCVD状态)2、已完成连接的队列(ESTABLISHED状态)但是两个队列长度之和不能超过backlog
      

      
      
  • accept函数
    • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      
      sockfd:服务器套接字addr:将返回对等方的套接字地址, 不关心的话, 可以设置为NULLaddrlen:返回对等方的套接字地址长度, 不关心的话可以设置成为NULL, 否则一定要初始化
  • connect函数
    • int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      
      建立一个连接至addr所指定的套接字参数:sockfd:未连接套接字addr:要连接的套接字地址addrlen:第二个参数addr长度
  • inet_aton
    •   将一个字符串的ip地址字节转换成了一个一个32位的网络序列IP地址

      int inet_aton(const char *string, struct in_addr*addr);
      
      string是表示的是要转换的字符串ip地址,后面的是网络序列ip地址成功返回非0,不成功返回-1
  • 客户端和服务器端练习(server\client)
    •   分别建立两个工程,一个server,一个client。然后先打开服务端,再打开客户端进行测试,源代码如下。

      //服务器端
      #pragma comment(lib,"ws2_32.lib")
      #include<iostream>
      #include<winsock2.h>
      #include<string>
      #include<stdio.h>
      using namespace std;
      
      int main(){
          //创建套接字
          WORD myVersionRequest;
          WSADATA wsaData;                          //包含系统所支持的winsocket版本信息
          myVersionRequest = MAKEWORD(1, 1);        //初始化版本1.1
          int err;
          err = WSAStartup(myVersionRequest, &wsaData);
      
          if (!err){
              cout << "已经打开套接字" << endl;
          }
          else{
              //进一步绑定套接字
              cout << "套接字未打开" << endl;
              return 0;
          }
      
          //创建可识别套接字  调用socket函数
          SOCKET serSocket = socket(AF_INET, SOCK_STREAM, 0);
      
          //需要绑定的参数
          SOCKADDR_IN addr;
          addr.sin_family = AF_INET;
          addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址
          addr.sin_port = htons(3000);//绑定端口
      
          //将套接字绑定到指定的网络地址
          bind(serSocket, (SOCKADDR*)&addr, sizeof(SOCKADDR));//绑定完成
          //监听连接
          listen(serSocket, 10);                               //第二个参数代表能够接受的最多的连接数
          //建立客户端的连接
          SOCKADDR_IN clientsocket;
          int len = sizeof(SOCKADDR);
          SOCKET serConn;
          //等待客户端的连接
          serConn = accept(serSocket, (SOCKADDR*)&clientsocket, &len);      //返回一个数字  接受函数,不是-1就是接受连接成功
          cout << "客户端" << inet_ntoa(clientsocket.sin_addr) << "已连接" << endl;             //客户端已连接
      
          while (1) {
              char sendBuf[100];                              //发送的字节
              sprintf_s(sendBuf, "server : welcome %s to server.", inet_ntoa(clientsocket.sin_addr));    //转换函数,将二进制的ip序列转换成char数组
              //在对应的IP处并且将这行字打印到那里
              send(serConn, sendBuf, strlen(sendBuf) + 1, 0);
              char receiveBuf[100];                          //收到的字节
              //接收客户端传来的信息
              recv(serConn, receiveBuf, strlen(receiveBuf) + 1, 0);
              char* quit = "quit";
              //如果客户端传来了quit信号,则服务端关闭,客户端也关闭
              if (!strcmp(receiveBuf, quit)) {
                  break;
              }
              printf("%s\n", receiveBuf);
          }
      
          closesocket(serConn);   //关闭
          WSACleanup();           //释放资源的操作
      }
      //客户端
      #pragma comment(lib,"ws2_32.lib")
      #include<winsock2.h>
      #include<iostream>
      #include<string>
      #include<conio.h>
      using namespace std;
      int main(){
      
          WORD versionRequired;
          WSADATA wsaData;                            //包含系统所支持的WinStock版本信息
          versionRequired = MAKEWORD(1, 1);           //初始化版本1.1
          int err;
          //注册WinStock,返回状态
          err = WSAStartup(versionRequired, &wsaData);//协议库的版本信息
          if (!err)   {                                //返回结果为0表示初始化失败{
              cout << LPSTR("客户端套接字已经打开!\n");
      }
          else{
              //调用WSAGetLastError()查看错误信息
              cout << ("客户端套接字打开失败:") << WSAGetLastError() << endl;
              return 0;//结束
          }
          /*
          创建套接字:
          流式套接字:   SOCK_STREAM , IPPROTO_TCP
          数据报套接字:  SOCK_DGRAM  , IPPROTO_UDP
          */
      
          SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    //创建流式套接字
          SOCKADDR_IN clientsock_in;                                          //专门针对Internet 通信域的Winsock地址结构
          clientsock_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");        //通过inet_addr结构指定套接字的主机IP地址
          clientsock_in.sin_family = AF_INET;                                 //指定协议家族:AF_INET
          clientsock_in.sin_port = htons(3000);                               //指定将要分配给套接字的传输层端口号:6000
      
          //开始连接
          int fail = connect(clientSocket, (SOCKADDR*)&clientsock_in, sizeof(SOCKADDR));
          if (fail){
              cout << "与服务端连接失败!程序将退出..." << endl;
              _getch();
              return 0;
          }
          string s;
          while (cin >> s){
              char receiveBuf[100];
              //接收数据
              recv(clientSocket, receiveBuf, 101, 0);
              cout << receiveBuf << endl;
              //发送数据
              send(clientSocket, s.c_str(), s.length() + 1, 0);
              if (s == "quit"){
                  break;
              }
          }
          closesocket(clientSocket);//关闭套接字
      
          if (WSACleanup() == SOCKET_ERROR){
              cout << "套接字关闭失败:" << WSAGetLastError() << endl;
          }
          else{
              cout << "套接字成功关闭." << endl;
          }
          _getch();
          return 0;
      }
    •   程序运行截图

#pragma comment(lib,"ws2_32.lib")#include<iostream>#include<winsock2.h>#include<string>#include<stdio.h>using namespace std;
int main(){//创建套接字WORD myVersionRequest;WSADATA wsaData;                          //包含系统所支持的winsocket版本信息myVersionRequest = MAKEWORD(1, 1);        //初始化版本1.1int err;err = WSAStartup(myVersionRequest, &wsaData);
if (!err){cout << "已经打开套接字" << endl;}else{//进一步绑定套接字cout << "套接字未打开" << endl;return 0;}
//创建可识别套接字  调用socket函数SOCKET serSocket = socket(AF_INET, SOCK_STREAM, 0);
//需要绑定的参数SOCKADDR_IN addr;addr.sin_family = AF_INET;addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址addr.sin_port = htons(3000);//绑定端口
//将套接字绑定到指定的网络地址bind(serSocket, (SOCKADDR*)&addr, sizeof(SOCKADDR));//绑定完成//监听连接listen(serSocket, 10);                               //第二个参数代表能够接受的最多的连接数//建立客户端的连接SOCKADDR_IN clientsocket;int len = sizeof(SOCKADDR);SOCKET serConn;//等待客户端的连接serConn = accept(serSocket, (SOCKADDR*)&clientsocket, &len);      //返回一个数字  接受函数,不是-1就是接受连接成功cout << "客户端" << inet_ntoa(clientsocket.sin_addr) << "已连接" << endl;             //客户端已连接
while (1) {char sendBuf[100];                              //发送的字节sprintf_s(sendBuf, "server : welcome %s to server.", inet_ntoa(clientsocket.sin_addr));    //转换函数,将二进制的ip序列转换成char数组//在对应的IP处并且将这行字打印到那里send(serConn, sendBuf, strlen(sendBuf) + 1, 0);char receiveBuf[100];                          //收到的字节//接收客户端传来的信息recv(serConn, receiveBuf, strlen(receiveBuf) + 1, 0);char* quit = "quit";//如果客户端传来了quit信号,则服务端关闭,客户端也关闭if (!strcmp(receiveBuf, quit)) {break;}printf("%s\n", receiveBuf);}
closesocket(serConn);   //关闭WSACleanup();           //释放资源的操作}

时间: 2024-11-16 10:41:21

Socket编程--基础(基本server/client实现)的相关文章

c#socket编程基础 [转帖]

c#socket编程基础 Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类可以开发多种网络应用程序..Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要--从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应Int

socket编程基础3

服务器端尽可能使用RUSEADDR. 在绑定之前尽可能调用setsockopt来设置SO_REUSEADDR套接字选项. 使用SO_REUSEADDR选项可以使得不必等待TIME_WAIT状态消失就可以重启服务器. fork()产生一个进程来处理客户端与服务器端之间的消息.父进程保持监听状态连接.accept返回多个已连接套接字! echocli.c #include <unistd.h> #include <sys/types.h> #include <sys/socket

socket编程基础2

包含头文件<sys/socket.h> 功能:创建一个套接字用于通信 原型 int socket(int domain, int type, int protocol); 参数 domain :指定通信协议族(protocol family) type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW protocol :协议类型 返回值:成功返回非负整数, 它与文件描述符类似,我们把它称为套接口描述字,简称套接字.失败返回-

一个linux下socket编程的例子,client连server

关于socket编程,以下文章写得比较好:http://www.cnblogs.com/xudong-bupt/archive/2013/12/29/3483059.html 1. accept()函数,如果客户端一直没有连接,则服务端阻塞在accept()函数处. 以下是client代码 //============================================================================ // Name : client.cpp // A

java socket编程基础(转)

一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

你得学会并且学得会的Socket编程基础知识

这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解. 本文源代码,可以通过这里下载 http://files.cnblogs.com/chenxizhang/SocketWorkshop.rar 第一步:创建解决方案 第二步:创建服务端程序 这里可以选择“Console Application”这个类型,比较方便调试 然后编写如下代码,实现服务器的基本功能 using System; using System.Coll

Java从零开始学四十五(Socket编程基础)

一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

c#socket编程基础

Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类可以开发多种网络应用程序..Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要--从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应Internet不断扩展的需要.

Java Socket编程基础及深入讲解

Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要讲解Socket的基础编程.Socket用在哪呢,主要用在进程间,网络间通信.本篇比较长,特别做了个目录: 一.Socket通信基本示例 二.消息通信优化 2.1 双向通信,发送消息并接受消息 2.2 使用场景 2.3 如何告知对方已发送完命令 2.3.1 通过Socket关闭 2.3.2 通过Socket关闭输出流的方式 2.3.3 通过约定符号 2.3.4 通过指定长度 三.服务端优化 3.1 服务端并发处理能力 3.2