zoukankan      html  css  js  c++  java
  • C语言写了一个socket client端,适合windows和linux,用GCC编译运行通过

    ///////////////////////////////////////////////////////////////////////////////
    /*
    gcc -Wall -o c1 c1.c -lws2_32
    */
    ///////////////////////////////////////////////////////////////////////////////

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>

    #define _WIN32_WINNT 0x501
    #define PORT 4000
    #define IP_ADDRESS "127.0.0.1"
    ///////////////////////////////////////////////////////////////////////////////
    // SK

    #ifdef _WIN32_WINNT
    #include <ws2tcpip.h>
    #include <winsock2.h>
    #else
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/un.h>
    #include <netdb.h>
    #endif

    ///////////////////////////////////////////////////////////////////////////////
    // SK

    void connect_inet_socket( int *psockfd, const char* host, int port );

    #ifdef _WIN32_WINNT
    void connect_windows_socket( int *psockfd, const char* pathname );
    #else
    void connect_unix_socket( int *psockfd, const char* pathname );
    #endif

    void writebuffer_socket( int sockfd, const void *data, int len );
    void readbuffer_socket( int sockfd, void *data, int len );
    void shutdown_socket( int sockfd );

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Access to sockets needs to be done with a wrapper function 'connect_socket'
    and it is substituted by 'connect_windows_socket' or by 'connect_unix_socket'
    ( depends on a state of the macro _WIN32 ) during preprocessing phase of
    the compilation.
    For portability 'connect_windows_socket' and 'connect_unix_socket' shouldn't
    be used directly and the wrapper function 'connect_socket' must be used instead.
    */

    #ifdef _WIN32_WINNT
    #define connect_socket connect_windows_socket
    #else
    #define connect_socket connect_unix_socket
    #endif

    int socket_desc;
    struct sockaddr_in server;

    ///////////////////////////////////////////////////////////////////////////////
    /* Opens an internet socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    port: The port number for the socket to be created. Low numbers are
    often reserved for important channels, so use of numbers of 4
    or more digits is recommended.
    host: The name of the host server.
    */

    void connect_inet_socket( int *psockfd, const char* host, int port )
    {
    int sockfd, ai_err;

    // creates an internet socket

    // fetches information on the host
    struct addrinfo hints, *res;
    char service[256];

    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    hints.ai_flags = AI_PASSIVE;

    //sprintf(service, "%d", port); // convert the port number to a string
    //ai_err = getaddrinfo(host, service, &hints, &res);
    //if (ai_err!=0) {
    // printf("Error code: %i ",ai_err);
    // perror("Error fetching host data. Wrong host name?");
    // exit(-1);
    //}

    // creates socket
    //sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    sockfd = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (sockfd < 0) {
    perror("Error opening socket");
    exit(-1);
    }
    else
    {
    printf("creates socket:%d ", sockfd);
    }

    // makes connection
    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
    perror("Error opening INET socket: wrong port or server unreachable");
    exit(-1);
    }
    freeaddrinfo(res);

    *psockfd = sockfd;
    }

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Opens a socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    pathname: The name of the file to use for sun_path.
    */

    #ifdef _WIN32_WINNT

    void connect_windows_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Windows

    // ...
    }

    #else

    void connect_unix_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Unix

    int sockfd, ai_err;

    struct sockaddr_in serv_addr;

    printf("Connecting to :%s: ",pathname);

    // fills up details of the socket addres
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sun_family = AF_UNIX;
    /* Beware of buffer over runs
    UNIX Network Programming by Richard Stevens mentions
    that the use of sizeof() is ok, but see
    http://mail-index.netbsd.org/tech-net/2006/10/11/0008.html
    */
    if ((int)strlen(pathname)> sizeof(serv_addr.sun_path)) {
    perror("Error opening UNIX socket: pathname too long ");
    exit(-1);
    } else {
    strcpy(serv_addr.sun_path, pathname);
    }
    // creates a unix socket

    // creates the socket
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

    // connects
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
    perror("Error opening UNIX socket: path unavailable, or already existing");
    exit(-1);
    }
    *psockfd = sockfd;
    }

    #endif

    ///////////////////////////////////////////////////////////////////////////////
    /* Writes to a socket.

    Args:
    sockfd: The id of the socket that will be written to.
    data: The data to be written to the socket.
    len: The length of the data in bytes.
    */

    void writebuffer_socket( int sockfd, const void *data, int len )
    {
    int n;

    n = write(sockfd, (char *) data, len);
    if (n < 0) {
    perror("Error writing to socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Reads from a socket.

    Args:
    sockfd: The id of the socket that will be read from.
    data: The storage array for data read from the socket.
    len: The length of the data in bytes.
    */

    void readbuffer_socket( int sockfd, void *data, int len )
    {
    int n, nr;
    char *pdata;

    pdata = (char *) data;
    n = nr = read(sockfd, pdata, len);

    while (nr > 0 && n < len) {
    nr = read(sockfd, &(pdata[n]), len - n);
    n += nr;
    }
    if (n == 0) {
    perror("Error reading from socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Shuts down the socket.
    */

    void shutdown_socket( int sockfd )
    {
    shutdown( sockfd, 2 );
    close( sockfd );
    }

    DWORD WINAPI ClientThread(LPVOID lpParameter)
    {
    SOCKET CientSocket = (SOCKET)lpParameter;
    int Ret = 0;
    char RecvBuffer[1024];

    while ( 1 )
    {
    memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
    Ret = recv(CientSocket, RecvBuffer, 1024, 0);
    if ( Ret == 0 || Ret == SOCKET_ERROR )
    {
    printf("服务端退出!");
    break;
    }

    }
    printf("接收到服务端的信息为%s", RecvBuffer);

    return 0;
    }


    int main(int argc, char * argv[])
    {
    WSADATA Ws;
    SOCKET ClientSocket;
    struct sockaddr_in ServerAddr;
    int Ret = 0;
    int AddrLen = 0;
    HANDLE hThread = NULL;
    char SendBuffer[MAX_PATH];
    int str_len;
    char RecvBuffer[30];

    //Init Windows Socket
    if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
    {
    printf("Init Windows Socket Failed");
    return -1;
    }
    //Create Socket
    ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if ( ClientSocket == INVALID_SOCKET )
    {
    printf("Create Socket Failed");
    return -1;
    }

    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    ServerAddr.sin_port = htons(PORT);
    memset(ServerAddr.sin_zero, 0x00, 8);

    Ret = connect(ClientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
    if ( Ret == SOCKET_ERROR )
    {
    printf("Connect Error");
    return -1;
    }
    else
    {
    printf("连接成功! ");
    }

    //read(ClientSocket, RecvBuffer, sizeof(RecvBuffer) - 1);
    str_len = recv(ClientSocket, RecvBuffer, 30, 0);
    RecvBuffer[str_len] = '';
    printf("Message from server: %s ", RecvBuffer);

    while ( 1 )
    {
    //cin.getline(SendBuffer, sizeof(SendBuffer));
    printf("Enter the Send infos- ");
    scanf("%s", SendBuffer);
    Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
    if ( Ret == SOCKET_ERROR )
    {
    printf("Send Info Error");
    break;
    }

    /*
    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
    if ( hThread == NULL )
    {
    printf("Create Thread Failed!");
    break;
    }

    CloseHandle(hThread);
    */
    printf("开始接收!");
    //str_len = read(ClientSocket, RecvBuffer, sizeof(RecvBuffer) - 1);
    //str_len = read(ClientSocket, RecvBuffer, sizeof(RecvBuffer) - 1);
    //str_len = read(ClientSocket, RecvBuffer, sizeof(RecvBuffer) - 1);
    str_len = recv(ClientSocket, RecvBuffer, 30, 0);
    if (str_len == -1)
    printf("read() error!");
    else
    printf("接受到的返回消息:%s",RecvBuffer);
    }

    closesocket(ClientSocket);
    WSACleanup();

    return 0;
    }

  • 相关阅读:
    「BZOJ4763」雪辉
    「CSA72」MST
    「CSA49」Bunny on Number Line
    「CSA49」Card Collecting Game
    Java indexOf() 方法
    MySQL执行计划分析
    NIO编程
    数据结构可视化
    深入理解二阶段提交协议(DDB对XA悬挂事务的处理分析)(一)
    linux下nohup日志切割方案
  • 原文地址:https://www.cnblogs.com/bdccloudy/p/7678626.html
Copyright © 2011-2022 走看看