admin 发表于 2020-5-9 02:14:22

一个简单的C语言的socket服务器和客户端程序

程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
客户端程序:client.cpp
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_PORT       5150
#define DEFAULT_BUFFER   2048

charszServer,
   szMessage;
intiPort    = DEFAULT_PORT;

int main()
{
   WSADATA      wsd;
   SOCKET       sClient;
   char         szBuffer;
   int          ret;
    struct sockaddr_in server;
    struct hostent    *host = NULL;
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
       printf("Failed to load Winsock library!\n");
       return 1;
    }
   printf("Enter a string to send to server:\n");
   gets(szMessage);
    // Create the socket, and attempt to connect to the server
    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sClient == INVALID_SOCKET)
    {
       printf("socket() failed: %d\n", WSAGetLastError());
       return 1;
    }
   server.sin_family = AF_INET;
   server.sin_port = htons(iPort);
   server.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (connect(sClient, (struct sockaddr *)&server,
       sizeof(server)) == SOCKET_ERROR)
    {
       printf("connect() failed: %d\n", WSAGetLastError());
       return 1;
    }
    // Send and receive data
    ret = send(sClient, szMessage, strlen(szMessage), 0);
    if (ret == SOCKET_ERROR)
    {
       printf("send() failed: %d\n", WSAGetLastError());
    }
    else{
       printf("Send '%s' \n", szMessage);
       ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
       if (ret == SOCKET_ERROR){
         printf("recv() failed: %d\n", WSAGetLastError());
       }
       else{
         szBuffer = '\0';
         printf("RECV: '%s'\n",szBuffer);
       }
    }
   closesocket(sClient);

   WSACleanup();
    return 0;
}服务器程序:server.cpp
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_PORT       5150
#define DEFAULT_BUFFER   4096

int   iPort   = DEFAULT_PORT;
char   szAddress;

DWORD WINAPI ClientThread(LPVOID lpParam)
{
   SOCKET       sock=(SOCKET)lpParam;
   char         szBuff;
   int          ret;

   while(1)
    {
       ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
       if (ret == 0)
         break;
       else if (ret == SOCKET_ERROR)
       {
         printf("recv() failed: %d\n", WSAGetLastError());
         break;
       }
       szBuff = '\0';
       printf("RECV: '%s'\n", szBuff);
      if(strcmp(szBuff,"abc")==0){
         memcpy(szBuff,"Send the correct string!",25);
       }
       else{
         memcpy(szBuff,"Send the wrong string!",23);
       }
       ret = send(sock, szBuff, strlen(szBuff), 0);
       if (ret == SOCKET_ERROR){
         printf("send() failed: %d\n", WSAGetLastError());
       }
    }
    return 0;
}

int main()
{
   WSADATA      wsd;
   SOCKET       sListen,
               sClient;
   int          iAddrSize;
   HANDLE       hThread;
   DWORD      dwThreadId;
    struct sockaddr_in local,
                      client;

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
       printf("Failed to load Winsock!\n");
       return 1;
    }
    // Create our listening socket
    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (sListen == SOCKET_ERROR)
    {
       printf("socket() failed: %d\n", WSAGetLastError());
       return 1;
    }
   local.sin_addr.s_addr = htonl(INADDR_ANY);
   local.sin_family = AF_INET;
   local.sin_port = htons(iPort);

    if (bind(sListen, (struct sockaddr *)&local,
         sizeof(local)) == SOCKET_ERROR)
    {
       printf("bind() failed: %d\n", WSAGetLastError());
       return 1;
    }
   listen(sListen, 8);
    // In a continous loop, wait for incoming clients. Once one
    // is detected, create a thread and pass the handle off to it.
    while (1)
    {
       iAddrSize = sizeof(client);
       sClient = accept(sListen, (struct sockaddr *)&client,
                     &iAddrSize);      
       if (sClient == INVALID_SOCKET)
       {      
         printf("accept() failed: %d\n", WSAGetLastError());
         break;
       }
       printf("Accepted client: %s:%d\n",
         inet_ntoa(client.sin_addr), ntohs(client.sin_port));

       hThread = CreateThread(NULL, 0, ClientThread,
                   (LPVOID)sClient, 0, &dwThreadId);
       if (hThread == NULL)
       {
         printf("CreateThread() failed: %d\n", GetLastError());
         break;
       }
       CloseHandle(hThread);
    }
   closesocket(sListen);
   
   WSACleanup();
    return 0;
}




admin 发表于 2020-5-9 02:16:45

作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。

作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。

Server:
#include <winsock2.h>
#pragma comment(lib, "WS2_32.lib")

#include <stdio.h>
void main()
{
    WORD wVersionRequested;//版本号
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
    //加载套接字库,如果失败返回
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0)
    {
      return;
    }

    //判断高低字节是不是2,如果不是2.2的版本则退出
    if (LOBYTE(wsaData.wVersion) != 2 ||
         
      HIBYTE(wsaData.wVersion) != 2)
         
    {
      return;
    }
   
         //创建流式套接字,基于TCP(SOCK_STREAM)

         SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);

         //Socket地址结构体的创建

         SOCKADDR_IN addrSrv;

         addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
         addrSrv.sin_family = AF_INET;//指定地址簇
         addrSrv.sin_port = htons(6000);
      //指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换

         //将套接字绑定到一个端口号和本地地址上
         bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行

         listen(socSrv, 5);
         
         SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体

         int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof

         //循环等待接受客户端发送请求

         while (1)
         {
                   //等待客户请求到来;当请求到来后,接受连接请求,

                   //返回一个新的对应于此次连接的套接字(accept)。
                   //此时程序在此发生阻塞

                   SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);

                   char sendBuf;

                   sprintf(sendBuf, "Welcome %s to JoyChou",

                            inet_ntoa(addrClient.sin_addr));//格式化输出

                   //用返回的套接字和客户端进行通信

                   send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节

                   //接收数据

                   char recvBuf;

                   recv(sockConn, recvBuf, 100, 0);

                   printf("%s\n", recvBuf);
                   closesocket(sockConn);

         }
}


Client:

#include <winsock2.H>
#pragma comment(lib, "Ws2_32.lib")
#include <stdio.h>
#include <string.h>

void main()
{   
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
   
    wVersionRequested = MAKEWORD( 2, 2 );
   
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
         
      return;
    }
   
   
    if ( LOBYTE( wsaData.wVersion ) != 2 ||
      HIBYTE( wsaData.wVersion ) != 2 )
    {
         
      WSACleanup( );
      return;
    }
    SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
   
    connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    char recvBuf;
    char sendBuf[] = "This is Joychou";
    recv(socketClient, recvBuf, 256, 0);
    printf("%s\n", recvBuf);
    send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
    closesocket(socketClient);
    WSACleanup();
   
}

页: [1]
查看完整版本: 一个简单的C语言的socket服务器和客户端程序