Сокеты - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Написал простой TCP клинет
#include <winsock2.h>
#include <stdio.h>
int main(void)
{
    WORD v=MAKEWORD(2,0);
    WSADATA d;
    int e=WSAStartup(v,&d);
    if (e)
    {
        perror("error initializing winsock");
        return 1;
    }
    struct sockaddr_in peer;
    int s;
    int rc;
    char buf[1];
    peer.sin_family=AF_INET;
    peer.sin_port=htons(7500);
    peer.sin_addr.s_addr=inet_addr("127.0.0.1");
    s=socket(AF_INET,SOCK_STREAM,0);
    if (s<0)
    {
        perror("error calling socket");
        return 1;
    }
    rc=connect(s,(struct sockaddr *)&peer,sizeof(peer));
    if (rc)
    {
        perror("error calling connect");
        return 1;
    }
    rc=send(s,"1",1,0);
    if (rc<=0)
    {
        perror("error calling send");
        return 1;
    }
    rc=recv(s,buf,1,0);
    if (recv<=0)
        perror("error calling recv");
    else
        printf("%c\n",buf[0]);
    return 0;
}
и TCP сервер
#include <winsock2.h>
#include <stdio.h>
int main(void)
{
    WORD v=MAKEWORD(2,0);
    WSADATA d;
    int e=WSAStartup(v,&d);
    if (e)
    {
        perror("error initializing winsock");
        return 1;
    }
    struct sockaddr_in local;
    int s;
    int s1;
    int rc;
    char buf[1];
    local.sin_family=AF_INET;
    local.sin_port=htons(7500);
    local.sin_addr.s_addr=htonl(INADDR_ANY);
    s=socket(AF_INET,SOCK_STREAM,0);
    if (s<0)
    {
        perror("error calling socket");
        return 1;
    }
    rc=bind(s,(struct sockaddr *)&local,sizeof(local));
    if (rc<0)
    {
        perror("error calling bind");
        return 1;
    }
    rc=listen(s,5);
    if (rc)
    {
        perror("error calling listen");
        return 1;
    }
    s1=accept(s,NULL,NULL);
    if (s1<0)
    {
        perror("error calling accept");
        return 1;
    }
    rc=recv(s1,buf,1,0);
    if (rc<=0)
    {
        perror("error calling recv");
        return 1;
    }
    printf("%c\n",buf[0]);
    rc=send(s1,"2",1,0);
    if (rc<=0)
        perror("error calling send");
    return 0;
}
в первый раз когда запустил было все нормально клиент выводил 2 а сервер 1. Но во второй раз сервер вывел 1 а клиент нечего. Как это можно исправить?
Исправил, оказывается забыл закрыть сокеты. Если кому надо вот исправленные клиент и сервер. клинет
#include <winsock2.h>
#include <stdio.h>
int main(void)
{
    WORD v=MAKEWORD(2,0);
    WSADATA d;
    int e=WSAStartup(v,&d);
    if (e)
    {
        perror("error initializing winsock");
        return 1;
    }
    struct sockaddr_in peer;
    int s;
    int rc;
    char buf[1];
    peer.sin_family=AF_INET;
    peer.sin_port=htons(7500);
    peer.sin_addr.s_addr=inet_addr("127.0.0.1");
    s=socket(AF_INET,SOCK_STREAM,0);
    if (s<0)
    {
        perror("error calling socket");
        return 1;
    }
    rc=connect(s,(struct sockaddr *)&peer,sizeof(peer));
    if (rc)
    {
        perror("error calling connect");
        return 1;
    }
    rc=send(s,"1",1,0);
    if (rc<=0)
    {
        perror("error calling send");
        return 1;
    }
    rc=recv(s,buf,1,0);
    if (recv<=0)
        perror("error calling recv");
    else
        printf("%c\n",buf[0]);
    if (closesocket(s))
        perror("error calling closesocket");
    WSACleanup();
    return 0;
}
сервер
#include <winsock2.h>
#include <stdio.h>
int main(void)
{
    WORD v=MAKEWORD(2,0);
    WSADATA d;
    int e=WSAStartup(v,&d);
    if (e)
    {
        perror("error initializing winsock");
        return 1;
    }
    struct sockaddr_in local;
    int s;
    int s1;
    int rc;
    char buf[1];
    local.sin_family=AF_INET;
    local.sin_port=htons(7500);
    local.sin_addr.s_addr=htonl(INADDR_ANY);
    s=socket(AF_INET,SOCK_STREAM,0);
    if (s<0)
    {
        perror("error calling socket");
        return 1;
    }
    rc=bind(s,(struct sockaddr *)&local,sizeof(local));
    if (rc<0)
    {
        perror("error calling bind");
        return 1;
    }
    rc=listen(s,5);
    if (rc)
    {
        perror("error calling listen");
        return 1;
    }
    s1=accept(s,NULL,NULL);
    if (s1<0)
    {
        perror("error calling accept");
        return 1;
    }
    rc=recv(s1,buf,1,0);
    if (rc<=0)
    {
        perror("error calling recv");
        return 1;
    }
    printf("%c\n",buf[0]);
    rc=send(s1,"2",1,0);
    if (rc<=0)
        perror("error calling send");
    if (closesocket(s))
        perror("error calling closesocket");
    if (closesocket(s1))
        perror("error calling closesocket");
    WSACleanup();
    return 0;
}

Решение задачи: «Сокеты»

textual
Листинг программы
#include "string.h"
#define Q (sockaddr*)
#define W send(((SOCKET*)cs)[0],str,strlen(str),0);
DWORD WINAPI CLIENT(LPVOID cs);
DWORD WINAPI CONEKT(LPVOID ss);
 
int main()
{
    WSADATA wsa;
    WSAStartup(0x202,&wsa);
    int n;
    SOCKET s;
    sockaddr_in ss;
    s=socket(AF_INET,SOCK_STREAM,0);
    ss.sin_family=AF_INET;
    ss.sin_port=htons(666);
    ss.sin_addr.s_addr=0;
    bind(s,Q &ss,sizeof(ss));
    listen(s,5);
    DWORD thID;
    CreateThread(0,0,CONEKT,&s,0,&thID);
label:
    system("pause");
    goto label;
        return 0;   
}
 
DWORD WINAPI CONEKT(LPVOID ss)
{
DWORD thID;
SOCKET cs;
sockaddr_in css_in;
int size_css_in=sizeof(css_in);
while((cs=accept(((SOCKET*)ss)[0],Q &css_in,&size_css_in)))
    CreateThread(0,0,CLIENT,&cs,0,&thID);}  
 
 
DWORD WINAPI CLIENT(LPVOID cs)
{
char str=0;
SOCKET s=((SOCKET*)cs)[0];
timeval tim;
fd_set rv;
tim.tv_sec=0;
tim.tv_usec=100;
FD_ZERO(&rv);
FD_SET(s,&rv);
select(s,&rv,0,0,0);
for(;;)
{
      if(FD_ISSET(s,&rv))
      {
       recv(s,&str,1,0);
       printf("%c",str);
    }
}
return 0;   
}

Объяснение кода листинга программы

  1. Включается заголовочный файл string.h для использования функций работы со строками.
  2. Определяется макрос Q, который преобразует указатель на структуру sockaddr в указатель на первый элемент этой структуры.
  3. Определяется макрос W, который отправляет данные по сокету.
  4. Определяются две функции: CLIENT и CONEKT, которые будут использоваться в многопоточной работе.
  5. В функции main создается дескриптор WSAData для работы с сокетами.
  6. Создается сокет s и привязывается к порту 666 на localhost.
  7. Создается поток, который будет прослушивать входящие подключения на сокете s.
  8. В бесконечном цикле в функции CONEKT принимается каждое входящее подключение и создается новый поток CLIENT для работы с клиентом.
  9. В функции CLIENT создается сокет s, который передается в функцию accept для принятия входящего подключения.
  10. В бесконечном цикле в функции CLIENT ожидается приход данных от клиента, которые затем выводятся на экран.
  11. Все используемые переменные и дескрипторы освобождаются, и программа завершается.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

12   голосов , оценка 3.333 из 5